对XDocument中的所有元素进行排序

Zer*_*ool 14 c# sorting linq-to-xml

我有一个XDocument,我想按字母顺序对所有元素进行排序.这是结构的简化版本:

<Config>
 <Server>
    <Id>svr1</Id>
    <Routing>
        <RoutingNodeName>route1</RoutingNodeName>
        <Subscription>
            <Id>1</Id>
        </Subscription>
        <RoutingParameters id="Routing1">
            <Timeout>7200</Timeout>
        </RoutingParameters>
    </Routing>
    <Storage>
            <Physical>HD1</Physical>
    </Storage>
 </Server>
 <Applications>
    <Services>
        <Local></Local>
    </Services>
 </Applications>
</Config>
Run Code Online (Sandbox Code Playgroud)

我想在各个级别对这些文档中的元素进行排序,到目前为止我能够像这样对它进行排序:

private static XDocument Sort(XDocument file)
{
    return new XDocument(
        new XElement(file.Root.Name,
            from el in file.Root.Elements()
            orderby el.Name.ToString()
            select el));
}
Run Code Online (Sandbox Code Playgroud)

哪个产生:

<Config>
<Applications>
  <Services>
    <Local></Local>
  </Services>
</Applications>
<Server>
  <Id>svr1</Id>
  <Routing>
    <RoutingNodeName>route1</RoutingNodeName>
    <Subscription>
      <Id>1</Id>
    </Subscription>
    <RoutingParameters id="Routing1">
      <Timeout>7200</Timeout>
    </RoutingParameters>
  </Routing>
  <Storage>
    <Physical>HD1</Physical>
  </Storage>
</Server>
</Config>
Run Code Online (Sandbox Code Playgroud)

我希望能够以相同的方式对所有子元素进行排序(理想情况下通过递归函数).任何想法我怎么能用LINQ得到这个?

谢谢你的任何想法.

dtb*_*dtb 20

您已经有了一种方法来对元素进行排序.只需递归应用它:

private static XElement Sort(XElement element)
{
    return new XElement(element.Name,
            from child in element.Elements()
            orderby child.Name.ToString()
            select Sort(child));
}

private static XDocument Sort(XDocument file)
{
    return new XDocument(Sort(file.Root));
}
Run Code Online (Sandbox Code Playgroud)

请注意,这会从文档中删除所有非元素节点(属性,文本,注释等).


如果要保留非元素节点,则必须将它们复制到:

private static XElement Sort(XElement element)
{
    return new XElement(element.Name,
            element.Attributes(),
            from child in element.Nodes()
            where child.NodeType != XmlNodeType.Element
            select child,
            from child in element.Elements()
            orderby child.Name.ToString()
            select Sort(child));
}

private static XDocument Sort(XDocument file)
{
    return new XDocument(
            file.Declaration,
            from child in file.Nodes()
            where child.NodeType != XmlNodeType.Element
            select child,
            Sort(file.Root));
}
Run Code Online (Sandbox Code Playgroud)


Arv*_*wen 15

这种方法可以实现真正的文档扩展并保留属性和文本值

我想出了这个基于几个不同的帖子和代码来自这里和那里...感谢所有贡献的人!

在同一个命名空间(不是同一个类)中添加以下内容......

public static void Sort(this XElement source, bool bSortAttributes = true)
{
    //Make sure there is a valid source
    if (source == null) throw new ArgumentNullException("source");

    //Sort attributes if needed
    if (bSortAttributes)
    {
        List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList();
        sortedAttributes.ForEach(a => a.Remove());
        sortedAttributes.ForEach(a => source.Add(a));
    }

    //Sort the children IF any exist
    List<XElement> sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList();
    if (source.HasElements)
    {
        source.RemoveNodes();
        sortedChildren.ForEach(c => c.Sort(bSortAttributes));
        sortedChildren.ForEach(c => source.Add(c));
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用文档扩展名...

//Load the xDoc
XDocument xDoc = XDocument.Load("c:\test.xml");

//Sort the root element
xDoc.Root.Sort();
Run Code Online (Sandbox Code Playgroud)