tags:

views:

153

answers:

2

I have an xml that I would like to get all of its elements. I tried getting those elements by Descendants() or DescendantNodes(), but both of them returned me repeated nodes

For example, here is my xml:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <FirstElement xsi:type="myType">
    <SecondElement>A</SecondElement> 
  </FirstElement>
</Root>

and when I use this snippet:

 XElement Elements = XElement.Parse(XML);
 IEnumerable<XElement> xElement = Elements.Descendants();
 IEnumerable<XNode> xNodes = Elements.DescendantNodes();
 foreach (XNode node in xNodes )
 {
     stringBuilder.Append(node);
 }

it gives me two nodes but repeating the <SecondElement>. I know Descendants call its children, and children of a child all the time, but is there any other way to avoid it?

Then, this is the content of my stringBuilder:

<FirstElement xsi:type="myType"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
   <SecondElement>A</SecondElement> 
</FirstElement>

<SecondElement>A</SecondElement>
+3  A: 

Well do you actually want all the descendants or just the top-level elements? If you only want the top level ones, then use the Elements() method - that returns all the elements directly under the current node.

The problem isn't that nodes are being repeated - it's that the higher-level nodes include the lower level nodes. So the higher-level node is being returned, then the lower-level one, and you're writing out the whole of both of those nodes, which means you're writing out the lower-level node twice.

If you just write out, say, the name of the node you're looking at, you won't see a problem. But you haven't said what you're really trying to do, so I don't know if that helps...

Jon Skeet
Eventually I want to only have <FirstElement xsi:type="myType"> <SecondElement>A</SecondElement> </FirstElement><FirstElement xsi:type="myType"> <SecondElement>B</SecondElement> </FirstElement>
paradisonoir
By "have" what exactly to you mean though? Are you *actually* writing these to a StringBuilder, or was just that just for diagnostics? It sounds like you may just need a call to Elements()
Jon Skeet
no I have to write them to a stringbuilder and store them.
paradisonoir
So call Elements() to get the top level elements, and write those out. They will include the lower level elements, as you've seen.
Jon Skeet
A: 
XmlDocument doc = new XmlDocument();
doc.LoadXml(XML);
XmlNodeList allElements = doc.SelectNodes("//*");
foreach(XmlElement element in allElements)
{
  // your code here
}
Greg
This results in the same behaviour.
AnthonyWJones
I think the Jon found the real problem was the writing out of all the nodes, not actually returning multiple nodes.
Greg
I corrected my question.
paradisonoir