1

I have an XML file :

  <School>
    <SchoolID>9</SchoolID>
    <SchoolID>3</SchoolID>
    <SchoolID>3</SchoolID>
    <SchoolID>3</SchoolID>
    <SchoolID>4</SchoolID>
    <SchoolID>1</SchoolID>
    <SchoolID>3</SchoolID>
    <SchoolID>9</SchoolID>
    <SchoolID>2</SchoolID>
  </School>

The expecting results should be like:

 <School>
    <SchoolID>1</SchoolID>
    <SchoolID>2</SchoolID>
    <SchoolID>3</SchoolID>
    <SchoolID>4</SchoolID>
    <SchoolID>9</SchoolID>
 </School>

My C# code:

var xdoc = XElement.Load(filePath + "input.xml");
var temp = xdoc.Descendants("SchoolID").OrderBy(x => x.Value).Distinct();
xdoc.Save(filePath + "output_final.xml");

However, the result does not change anything.

My temp value is what I want, how can I update my output xml result?

Many thanks.

DY

Daoming Yang
  • 1,325
  • 3
  • 20
  • 41
  • You should accept answers to your questions by clicking the hollow check next to your favorite answer for each question. Doing so will give you more reputation. – SLaks Dec 14 '09 at 18:18

3 Answers3

2

Your LINQ statement only creates a statement that can be executed later, it doesn't modify anything. The following solves it quickly:

var xdoc = XDocument.Load(filePath + "input.xml");
xdoc.Root.ReplaceAll(xdoc
    .Descendants("SchoolID")
    .DistinctBy(e => e.Value)
    .OrderBy(e => e.Value));
xdoc.Save(filePath + "output_final.xml");
Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
0

Like this:

var ids = xdoc.Descendants("SchoolID")
              .Select(x => int.Parse(x.Value))
              .Distinct()
              .OrderBy(x => x);

var newDoc = new XElement("School", ids.Select(i => new XElement("SchoolID", i));
newDoc.Save(filePath + "output_final.xml");

You ned to call int.Parse to make sure it sorts correctly if an ID is more than 10, and you need to call Select before Distinct because XElement is compared by reference, meaning that no two XElements are equal, even if they have the same content. You could write your own IEqualityComparer, but this way is much easier.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
0

I got another way to solve this problem by using XSLT.

<xsl:template match="SchoolID">
<xsl:if test="not(node()) or not(preceding-sibling::node()[.=string(current())])">
<SchoolID>
   <xsl:value-of select="SchoolID"/>
</SchoolID>
</xsl:if>   
</xsl:template>

This code dose not include sorting.

Thanks.

DY

Daoming Yang
  • 1,325
  • 3
  • 20
  • 41