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

发布于 2024-09-14 06:06:29 字数 1701 浏览 5 评论 0原文

我有一个 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>

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

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));
}

产生:

<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>

我希望能够对所有以相同的方式处理子元素(最好通过递归函数)。我有什么想法可以使用 LINQ 来实现这一点吗?

感谢您的任何想法。

I have a XDocument where I'd like to sort all of the elements alphabetically. Here's a simplified version of the structure:

<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>

I'm wanting to sort the elements in this documents at all levels, so far I'm able to sort it like so:

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));
}

Which produces:

<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>

I'd like to be able to sort all of the children elements in the same way (through a recursive function ideally). Any ideas how I can get this going with LINQ?

Thanks for any ideas.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尐籹人 2024-09-21 06:06:29

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

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));
}

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


如果你想保留非元素节点,你必须将它们复制过来:

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));
}

You already have a method to sort the elements. Just apply it recursively:

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));
}

Note that this strips all non-element nodes (attributes, text, comments, etc.) from your document.


If you want to keep the non-element nodes, you have to copy them over:

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));
}
预谋 2024-09-21 06:06:29

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

我根据一些不同的帖子和代码想出了这个方法...感谢所有贡献者!

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

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));
    }
}

要使用文档扩展名...

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

//Sort the root element
xDoc.Root.Sort();

THIS METHOD MAKES A REAL DOCUMENT EXTENSION AND PRESERVES THE ATTRIBUTES AND TEXT VALUES

I came up with this based off a few different posts and code from here and there... Thanks to all who contributed!

Within the same namespace (not the same class) add the following...

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));
    }
}

To use the document extension...

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

//Sort the root element
xDoc.Root.Sort();
紫瑟鸿黎 2024-09-21 06:06:29

这是一个更新的示例,其中将包括执行排序时的所有属性。

private static XElement Sort(XElement element)
{
    XElement newElement = new XElement(element.Name,
        from child in element.Elements()
        orderby child.Name.ToString()
        select Sort(child));
    if (element.HasAttributes)
    {
        foreach (XAttribute attrib in element.Attributes())
        {
            newElement.SetAttributeValue(attrib.Name, attrib.Value);
        }
    }
    return newElement;
}

private static XDocument Sort(XDocument file)
{
    return new XDocument(Sort(file.Root));
}

这篇文章对我帮助很大,因为我不想使用 XSLT 执行 XML 排序,因为我不想重新格式化 XML。我到处搜索一个简单的解决方案来使用 C# 和 ASP.NET 执行 XML 排序,当我找到这个线程时我很高兴。感谢所有人,这正是我所需要的。

Here is an updated example that will include all attributes when performing the sort.

private static XElement Sort(XElement element)
{
    XElement newElement = new XElement(element.Name,
        from child in element.Elements()
        orderby child.Name.ToString()
        select Sort(child));
    if (element.HasAttributes)
    {
        foreach (XAttribute attrib in element.Attributes())
        {
            newElement.SetAttributeValue(attrib.Name, attrib.Value);
        }
    }
    return newElement;
}

private static XDocument Sort(XDocument file)
{
    return new XDocument(Sort(file.Root));
}

This post helped me a lot, because I did not want to perform an XML sort using XSLT since I did not want to reformat the XML. I searched all around for a simple solution to perform an XML sort using C# and ASP.NET and I was delighted when I found this thread. Thanks to all, this did exactly what I needed.

寄与心 2024-09-21 06:06:29

我认为这些扩展方法效果最好。

public static class XmlLinq
{
  public static void Sort(this XElement source, bool sortAttributes = true)
  {
     if (source == null)
        throw new ArgumentNullException("source");

     if (sortAttributes)
        source.SortAttributes();

     List<XElement> sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList();
     source.RemoveNodes();

     sortedChildren.ForEach(c => source.Add(c));
     sortedChildren.ForEach(c => c.Sort());
  }

  public static void SortAttributes(this XElement source)
  {
     if (source == null)
        throw new ArgumentNullException("source");

     List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList();
     sortedAttributes.ForEach(a => a.Remove());
     sortedAttributes.ForEach(a => source.Add(a));
  }
}

I think these extension method work best.

public static class XmlLinq
{
  public static void Sort(this XElement source, bool sortAttributes = true)
  {
     if (source == null)
        throw new ArgumentNullException("source");

     if (sortAttributes)
        source.SortAttributes();

     List<XElement> sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList();
     source.RemoveNodes();

     sortedChildren.ForEach(c => source.Add(c));
     sortedChildren.ForEach(c => c.Sort());
  }

  public static void SortAttributes(this XElement source)
  {
     if (source == null)
        throw new ArgumentNullException("source");

     List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList();
     sortedAttributes.ForEach(a => a.Remove());
     sortedAttributes.ForEach(a => source.Add(a));
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文