使用LINQ对XML进行排序 [英] Sorting XML using LINQ

查看:57
本文介绍了使用LINQ对XML进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用LINQ对XML文件进行排序. XML在下面,仅作为示例.通常情况下,它更大,更复杂. XML应该按标题升序排列.不是一次完成整个XML,而是每个父节点本身.叶子总是在底部.文件夹或非叶子在顶部.以下XML已经结构良好,但是标题顺序错误.排序算法还应替换错误放置的非叶子节点. 我已经有一些可以完成此工作的代码,但是我想知道是否有更优雅或更短的方法.目前,我必须调用一个函数递归来进行遍历.也许这可以用另一种方式来完成. 谢谢.

I want to sort a XML file with LINQ. The XML is below and is only an example. Normally it is much bigger and more complex. The XML should be sorted by title, ascending. Not the whole XML at once, but every parentNode for itself. Leafs are always at the bottom. Folder or non-leafs are at the top. The following XML is already well structured, but the titles are in the wrong order. The sort algorithm should also replace wrong positioned non-leaf nodes. I have already some code which does the job, but I want to know if there is a more elegant or a shorter way. At the moment I have to call a function recursive to make the traversion. Maybe this can be done in another way. Thank you.

Rene

这是我的XML:

<Node title="text99" leaf="no">
<Node title="text98" leaf="no">
    <Node title="text97" leaf="no">
        <Node title="text96" leaf="yes"/>
        <Node title="text95" leaf="yes"/>
    </Node>
    <Node title="text94" leaf="no">
        <Node title="text93" leaf="yes"/>
        <Node title="text92" leaf="yes"/>
    </Node>
    <Node title="text91" leaf="yes"/>
    <Node title="text90" leaf="yes"/>
</Node>
<Node title="text89" leaf="no">
    <Node title="text88" leaf="no">
        <Node title="text87" leaf="yes"/>
        <Node title="text86" leaf="yes"/>
    </Node>
    <Node title="text85" leaf="no">
        <Node title="text84" leaf="yes"/>
        <Node title="text83" leaf="yes"/>
    </Node>
    <Node title="text82" leaf="yes"/>
    <Node title="text81" leaf="yes"/>
</Node>
<Node title="text80" leaf="no">
    <Node title="text79" leaf="no">
        <Node title="text78" leaf="no">
            <Node title="text78" leaf="yes"/>
            <Node title="text77" leaf="yes"/>
        </Node>
        <Node title="text76" leaf="no">
            <Node title="text75" leaf="yes"/>
            <Node title="text74" leaf="yes"/>
        </Node>
        <Node title="text73" leaf="yes"/>
        <Node title="text72" leaf="yes"/>
    </Node>
    <Node title="text71" leaf="no">
        <Node title="text70" leaf="no">
            <Node title="text69" leaf="yes"/>
            <Node title="text68" leaf="yes"/>
        </Node>
        <Node title="text67" leaf="no">
            <Node title="text66" leaf="yes"/>
        </Node>
        <Node title="text65" leaf="yes"/>
        <Node title="text64" leaf="yes"/>
    </Node>
    <Node title="text63" leaf="yes"/>
    <Node title="text62" leaf="yes"/>
</Node>
<Node title="text61" leaf="yes"/>
<Node title="text60" leaf="yes"/>

这是我的代码:

using (XmlReader reader = XmlReader.Create(XmlStream))
{
    XDocument xDoc = XDocument.Load(reader);                        
    Action<XElement> sortXml = null;
    sortXml = xElement =>
    {
    bool sortParentNode = false;
    foreach (var xElem in xElement.Elements())
    {                                    
        if (xElem.HasElements)
        {
            // go into deep
                sortXml(xElem);
        }
        else
            {
        // break loop and sort parentNode
        sortParentNode = true;
        break;
        }                                    
    }
    if (sortParentNode)
    {
        xElement.ReplaceNodes(from node in xElement.Elements()
                orderby node.Attribute("title").Value
                group node by node.HasElements into folderGroup
                orderby folderGroup.Key descending
                select folderGroup);
    }
};
sortXml(xDoc.Root);                        
}

推荐答案

XML应该按标题排序, 上升.不能一次完成整个XML, 但是每个parentNode本身.枫叶 总是在底部.文件夹或 非叶子在顶部.

The XML should be sorted by title, ascending. Not the whole XML at once, but every parentNode for itself. Leafs are always at the bottom. Folder or non-leafs are at the top.

此解决方案似乎符合您的要求:

This solution seems to fit your requirements:

public static void SortXml(XElement node)
{
    node.ReplaceNodes(node.Elements("Node")
        .OrderBy(x => (string)x.Attribute("leaf"))
        .ThenBy(x => (string)x.Attribute("title")));

    foreach (var childNode in node.Elements("Node"))
        SortXml(childNode);
}

...

XDocument doc = XDocument.Load("test.xml");
SortXml(doc.Root);

所有子节点都首先按leaf属性的值排序(使用字母"no"在字母"yes"之前的事实),然后按标题进行排序.所有第一级子节点都以这种方式排序,然后使用这些子节点中的每一个作为输入递归重复.

All child nodes are sorted by the value of the leaf attribute first (uses the fact that "no" comes before "yes" in alphabetical order), and by title secondary. All first level child nodes are sorted in this fashion, then repeat recursively using each of those child nodes as input.

输出:

<Node title="text99" leaf="no">
  <Node title="text80" leaf="no">
    <Node title="text71" leaf="no">
      <Node title="text67" leaf="no">
        <Node title="text66" leaf="yes" />
      </Node>
      <Node title="text70" leaf="no">
        <Node title="text68" leaf="yes" />
        <Node title="text69" leaf="yes" />
      </Node>
      <Node title="text64" leaf="yes" />
      <Node title="text65" leaf="yes" />
    </Node>
    <Node title="text79" leaf="no">
      <Node title="text76" leaf="no">
        <Node title="text74" leaf="yes" />
        <Node title="text75" leaf="yes" />
      </Node>
      <Node title="text78" leaf="no">
        <Node title="text77" leaf="yes" />
        <Node title="text78" leaf="yes" />
      </Node>
      <Node title="text72" leaf="yes" />
      <Node title="text73" leaf="yes" />
    </Node>
    <Node title="text62" leaf="yes" />
    <Node title="text63" leaf="yes" />
  </Node>
  <Node title="text89" leaf="no">
    <Node title="text85" leaf="no">
      <Node title="text83" leaf="yes" />
      <Node title="text84" leaf="yes" />
    </Node>
    <Node title="text88" leaf="no">
      <Node title="text86" leaf="yes" />
      <Node title="text87" leaf="yes" />
    </Node>
    <Node title="text81" leaf="yes" />
    <Node title="text82" leaf="yes" />
  </Node>
  <Node title="text98" leaf="no">
    <Node title="text94" leaf="no">
      <Node title="text92" leaf="yes" />
      <Node title="text93" leaf="yes" />
    </Node>
    <Node title="text97" leaf="no">
      <Node title="text95" leaf="yes" />
      <Node title="text96" leaf="yes" />
    </Node>
    <Node title="text90" leaf="yes" />
    <Node title="text91" leaf="yes" />
  </Node>
  <Node title="text60" leaf="yes" />
  <Node title="text61" leaf="yes" />
</Node>

这篇关于使用LINQ对XML进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆