使用linq对XMLDocument排序

本文关键字:排序 XMLDocument linq 使用 | 更新日期: 2023-09-27 18:04:25

我似乎不知道该怎么做。这里还有其他几个例子,但没有一个真正符合我想要做的:

考虑以下XMLDocument对象:

<Policy>
    <Covers>
        <MyCover1>
            <properties>
                <sortOrder>1</sortOrder>
            </properties>
        </MyCover1>
        <MyCover3>
            <properties>
                <sortOrder>3</sortOrder>
            </properties>
        </MyCover3>
        <MyCover2>
            <properties>
                <sortOrder>2</sortOrder>
            </properties>
        </MyCover2>
    </Covers>
</Policy>

我该如何使用linQ或其他方法基于节点"sortOrder"对该文档进行排序?

排序后的outerxml应该是这样的:

<Policy>
    <Covers>
        <MyCover1/>
        <MyCover2/>
        <MyCover3/>
    </Covers>
</Policy>

我已经取得了一些进展,数据现在排序了,但是我如何更新原始未排序的XmlDocument?这是我目前所看到的:

private static void DoSort(XmlDocument policyDocument)
{
    foreach(XmlNode coverGroup in policyDocument.SelectNodes("//CoverGroup"))
    {
        XDocument test = XDocument.Parse(coverGroup.OuterXml);
        var sorted = from xe in test.Element("CoverGroup").Elements()
             let so = xe.Element("properties").Element("displayOrder")
             let num = (int)so
             orderby num
             select xe;     
        var result = new XElement("CoverGroup", sorted);
    }
}

我需要将更改应用到"policyDocument"。注意:一个cover可以有它自己的CoverGroup,它也可以有它自己的CoverGroup。这至少下降了4级:即

<Policy>
<Covers>
    <MyCover1>
        <properties>
            <sortOrder></sortOrder>
        </properties>
        <CoverGroup>
            <MyCover1Child>
                <properties>
                    <sortOrder></sortOrder>
                </properties>
            </MyCover1Child>
        </CoverGroup>
    </MyCover1>
    ...
</Covers>

上面的XPATH和foreach连接了上述结构,所以我想也许只是用新的排序列表替换第一个foreach中的coverGroup XmlNode,但我不知道如何重建一个新的XmlNode。如果我们能弄清楚,那么我们可以简单地这样做:

policyDocument.ReplaceChild(coverGroup, mySortedXmlNode)

使用linq对XMLDocument排序

您可以尝试如下操作(使用XDocument,而不是XmlDocument):

var document = XDocument.Parse( /* the xml string */ );
var sorted = from xe in document.Element("Policy").Element("Covers").Elements()
             let so = xe.Element("properties").Element("sortOrder")
             let num = (int)so
             orderby num
             select xe;
var result = new XElement("Policy", new XElement("Covers", sorted));

我写的代码没有测试,但我认为应该是一个很好的起点。

如果您从一开始就使用XDocument,那么这样做将会很容易。它可以像这样简单:

XDocument doc = ...;
var baseElement = doc.XPathSelectElement("/Policy/Covers");
var sortedElements = baseElement.Elements()
    .OrderBy(e => (int)e.XPathSelectElement("properties/sortOrder"))
    .ToList(); // this call may or may not be needed, but just in case...
baseElement.ReplaceAll(sortedElements);

你的文档最终会被排序,你可以保存到你的XML文件或什么的。

一般来说,您不应该将常规DOM XmlDocument与LINQ XDocument API混合。选择其中之一。在我看来,LINQ to XML将是更好的选择。

使用Linq to xml排序xml。

var doc = XDocument.Parse(xmlString); //the xml string you want to sort
var sortedElements = (from x in doc.Descendants("properties")
                      orderby x.Element("sortOrder").Value
                      select new XElement(x.Parent.Name));
var outputResult = new XElement("Policy", new XElement("Covers", sortedElements));