开发者

Sort XMLDocument using linq

I can't seem to figure out how to do this. There are several other examples on here, but nothing really matches what I want to do:

Consider the following XMLDocument object:

<Policy>
    <Covers>
        <MyCover1>
            <properties>
                <sortOrder>1</sortOrder>
            </properties>
        </MyCover1>

        <MyCover3>
            <properties>
                <sortOrder>3</sortOrder>
            </properties>
        </MyCover3>

        <MyCover2>
            <properties>
                <sortOrder>2</sortOrder>
            </properties>
        </MyCov开发者_Python百科er2>
    </Covers>
</Policy>

How would I go about in sorting this document based on node "sortOrder" using linQ or another method?

After the sort the outerxml should basically look like this:

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

UPDATE

I've made some progress, the data is now sorted, but how do I update the original unsorted XmlDocument? This is what I have so far:

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

I need to apply the changes back to "policyDocument". Note: A cover can have a CoverGroup of it's own, which can then again have Covers with CoverGroups of it's own. This goes down at least 4 levels: ie

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

The XPATH and foreach above cathers for the above structure, so I was thinking of maybe just replacing the coverGroup XmlNode in the first foreach with the new sorted list, but I dont know how to reconstruct a new XmlNode. IF we can figure this out, then we can simply do this:

policyDocument.ReplaceChild(coverGroup, mySortedXmlNode)


You may try as follows (using XDocument, not 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));

I write the code without testing it, but I think should be a good starting point.


If you had started off with an XDocument from the start, doing this would have been easy. It could be as simple as doing this:

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

Your document would end up being sorted and you could save to your XML file or whatnot.

In general, you shouldn't be mixing the regular DOM XmlDocument with the LINQ XDocument API's. Choose one or the other. LINQ to XML will be the much nicer choice IMHO.


Sorting the xml using Linq to 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));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜