1

I have tried using Linq to xml it seems it is not working.in brief i want sorting based on Code attribute in code tag i want the xml as desired one i have tried doing it as below but it is not working Please help me out.

C#: Sort xml node using attribute value

Attempted Code: I have attempted this code i am not sure if it is proper way.

var orderedTabs = document.Root
    .Element("component")
    .Elements("intial")
    .Elements("second")
    .Elements("component")
    .Elements("observation")
    .OrderBy(xtab => (string)xtab.Element("code").Attribute("code").Value) 
    .ToList();

XML:

<component>
   <intial>
        <second>
            <component>
                <observation>
                    <templateId root="01"/>
                    <id root="01" />
                    <code code="BC3" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC1" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC2" />
                    <statusCode code="completed" />
                </observation>
            </component>
        </second>
    </intial>
    <intial>
        <second>
            <component>
                <observation>
                    <templateId root="01"/>
                    <id root="01" />
                    <code code="BC6" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC4" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC5" />
                    <statusCode code="completed" />
                </observation>
            </component>
        </second>
    </intial>
</component>

Desired output:

<component>
   <intial>
        <second>
            <component>
                <observation>
                    <templateId root="01"/>
                    <id root="01" />
                    <code code="BC1" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC2" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC3" />
                    <statusCode code="completed" />
                </observation>
            </component>
        </second>
    </intial>
    <intial>
        <second>
            <component>
                <observation>
                    <templateId root="01"/>
                    <id root="01" />
                    <code code="BC4" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC5" />
                    <statusCode code="completed" />
                </observation>
            </component>
            <component>
                <observation>
                    <templateId root="01" />
                    <id root="01" />
                    <code code="BC6" />
                    <statusCode code="completed" />
                </observation>
            </component>
        </second>
    </intial>
</component>
7
  • Welcome to StackOverflow. Please share with us what have you tried so far and where did you get stuck. Commented Jul 16, 2021 at 10:31
  • Thank you for responding @PeterCsala I have tried this but i do not know i am doing it in right way if this is wrong may i know the right way so i can sort the XML code var orderedTabs = document.Root.Element("component").Elements("intial").Elements("second").Elements("component").Elements("observation") .OrderBy(xtab => (string)xtab.Element("code").Attribute("code").Value) .ToList(); Commented Jul 16, 2021 at 11:19
  • Please amend/edit your post to include code Commented Jul 16, 2021 at 11:20
  • I am confused this is my first ever question to post in Stackoverflow may i know what exactly you are referring to Commented Jul 16, 2021 at 11:31
  • There is an Edit link under each post. You can click on that to alter your question to include more details. Commented Jul 16, 2021 at 11:34

2 Answers 2

1

You are only getting the elements and performing sort on it. This will just give a sorted output, but it won't change the xml document. You have to sort and then replace the unsorted elements with the sorted ones.

Given your structure you can do it like this -

var items = document.Element("component")
            .Elements("intial")
            .Elements("second");
foreach (var item in items)
{
    var tabs = item.Elements("component").Elements("observation");
    var orderedTabs = tabs
        .OrderBy(xtab => xtab.Element("code").Attribute("code").Value)
        .Select(s => new XElement("component", s))
        .ToList();
    item.ReplaceAll(orderedTabs);
}
Sign up to request clarification or add additional context in comments.

Comments

0

My solution:

var unorderedDocument = XDocument.Load("sample.xml");

var seconds = unorderedDocument.Descendants("second");
foreach (var second in seconds)
{
    var orderedComponents = second.Elements().OrderBy(t => t.Descendants("code").First().Attribute("code").ToString());
    second.ReplaceAll(orderedComponents.ToList());
}

using var memory = new MemoryStream();
unorderedDocument.Save(memory);
string orderedXml = Encoding.UTF8.GetString(memory.ToArray());
Console.WriteLine(orderedXml.ToString());

How does it work?

  • It parses the xml from a file (Descendants("second"))
  • It retrieves the <second> elements and all their children (Descendants("second"))
  • It iterates through the <second> nodes (foreach var second)
  • It orders the <component> (Elements) nodes based on the <code> node's code attribute
  • It replaces the original <second> node's children with the newly ordered <component> nodes (ReplaceAll)
  • It writes the whole document into a MemoryStream (Save)
  • It converts the MemoryStream to a string (Encoding.UTF8.GetString)
  • It prints out the result to the output
<?xml version="1.0" encoding="utf-8"?>
<component>
  <intial>
    <second>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC1" />
          <statusCode code="completed" />
        </observation>
      </component>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC2" />
          <statusCode code="completed" />
        </observation>
      </component>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC3" />
          <statusCode code="completed" />
        </observation>
      </component>
    </second>
  </intial>
  <intial>
    <second>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC4" />
          <statusCode code="completed" />
        </observation>
      </component>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC5" />
          <statusCode code="completed" />
        </observation>
      </component>
      <component>
        <observation>
          <templateId root="01" />
          <id root="01" />
          <code code="BC6" />
          <statusCode code="completed" />
        </observation>
      </component>
    </second>
  </intial>
</component>

Comments

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.