3

I've tried to find a solution for my problem, but my knowledge in this area (Linq, XML) is rather limited. :( 've found a simular construction, but I need a litte bit more complex way of sorting.

Consider the Following XML document:

<Envelope>
    <Body>
        <Table>
            <Trans>
                <B>1</B>
                <A>3</A>
                <C>5</C>
            </Trans>
            <Trans>
                <D>1</D>
                <A>6</A>
                <C>3</C>
            </Trans>
            <Trans>
                <A>1</A>
                <C>3</C>
                <B>5</B>
            </Trans>
        </Table>
    </Body>
<Envelope>

Is there any way I can sort the elements inside <Trans> using C#/Linq, or do I have to break up all <Trans> elements and sort them one by one?

Update I have a file and this is what I'm tring to accomplish. ;)

<Envelope>
    <Body>
       <Table>
           <Trans>
               <A>3</A>
               <B>1</B>
               <C>5</C>
           </Trans>
           <Trans>
               <A>6</A>
               <C>3</C>
               <D>1</D>
           </Trans>
           <Trans>
               <A>1</A>
               <B>5</B>
               <C>3</C>
           </Trans>
       </Table>
   </Body>
<Envelope>
4
  • 1
    Is the idea to come up with a new XML document, or just an in-memory representation? Commented Jun 20, 2012 at 10:02
  • Do you mean change the order they appear in the XML file? (In which case, why do you want to do this?) Commented Jun 20, 2012 at 10:03
  • 1
    I think he means that instead of <D>1</D><A>6</A><C>3</C> he wants to sort it into <A>6</A><C>3</C><D>1</D> in alphabetic order regardless of the integer values. Commented Jun 20, 2012 at 10:05
  • Matthew, you're right, that's what I'm trying to accomplish. Jon, it's a file. Commented Jun 20, 2012 at 10:06

2 Answers 2

3

It really depends on what exactly you want to do (process them in order, or reorder the XML?) and on what exactly you mean "sort" (sort by tag name? sort by value?).

If you just want to process them in order, this is how you can sort all elements inside each <Trans> by value (<D>1</D> before <A>6</A>):

XDocument doc = /* load up your XML */

var sorted = from trans in doc.Descendants("Trans")
             select trans.Children().OrderBy(c => int.Parse(c.Value)).ToArray();

Alternatively, here's how to order by tag name (<A>6</A> before <D>1</D>):

var sorted = from trans in doc.Descendants("Trans")
             select trans.Children().OrderBy(c => c.Name.LocalName).ToArray();

With the above, sorted will be an enumerable collection of arrays. Each array in the collection represents a <Trans>, and each such array holds the children of the <Trans> in order.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Jon, The alternative method is what I'm trying to accomplish. If I'm right, I can replace the elements in the original document like this? doc.Descendants("Trans").Remove(); doc.Element("Trans").Add(sorted);
@Rowdy.nl: L.B's code does exactly that, you only need to tack on a .ToArray() after the OrderBy :)
Thanks! I'm gonna give that a try :)Unfortunatly, I can't vote up bevause I don't have enough reputation... :/
2
XDocument xDoc = XDocument.Load(....);
foreach(var trans in xDoc.Descendants("Trans"))
{
    trans.ReplaceAll( trans.Elements().OrderBy(x=>x.Name.LocalName));
}

string newXml = xDoc.ToString();

5 Comments

This gives me this error? I'm guessing I'm missing some reference? 'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' does not contain a definition for 'OrderBy' and no extension method 'OrderBy' accepting a first argument of type 'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' could be found
Have you included System.Linq and System.Xml.Linq ?
@Rowdy Right click on the red underlined variable. Right click, then choose resolve - this will adding missing references for you, provided they are referenced or in the GAC.
Thanks, I'd already added those.. Just a small problem, xDoc.Descendants("Trans") does not return anything? The element is in the document; I can see it if I evealuate it in the Debugger... :/ At first I thought it could be because there wass al class attribute (<Trans class="entity">) but removing it did not give me any results. Any thoughts?
@Rowdy.nl xDoc.Descendants("Trans") returns IEnumerable<XElement> which should be enumerated to get the result(e.g foreach). You may also try to append .ToArray() to materialize it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.