tags:

views:

79

answers:

3

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

+2  A: 

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
Hi Yuriy, thanks very much. Is there any easy way I could get the xml file updated?
Daoming Yang
Working on that.
Yuriy Faktorovich
There is no `DistinctBy` method.
SLaks
Sorry the DistinctBy came from http://code.google.com/p/morelinq/wiki/OperatorsOverview
Yuriy Faktorovich
A: 

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
Maybe reverse the Distinct and OrderBy?
Yuriy Faktorovich
Very good idea.
SLaks
Thanks to Intellisense I found DistinctBy.
Yuriy Faktorovich
There is no `DistinctBy` method. http://stackoverflow.com/questions/520030/why-is-there-no-linq-method-to-return-distinct-values-by-a-predicate
SLaks
Had a feeling it came from MoreLinq/I created it. My fault.
Yuriy Faktorovich
Thank you Slakes and Yuriy. hoho...
Daoming Yang
A: 

Hi, 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