0

Given the following XML:

<Student number=2020 >
<Subject>Comp<Subject>
<Credintials>
<Password>....</Password>
</Credintials>
<PersonalDetails age=30 height=2/>
</Student>

I want to get:

Student
@number
Subject
Credintials
Password
PersonalDetails
@age
@height

in this order.

So basically if I Parse this XDocument, I get elements separately and attributes separately which disobeys the xml hierarchy.

   var attributes = xDocument.Descendants().Attributes();
   var elements = xDocument.Descendants().Elements();

I am looping this separately hence i am getting attributes first and then elements

Is there any way to list using the above order ?

hunch_hunch
  • 2,283
  • 1
  • 21
  • 26
Tee
  • 39
  • 1
  • 9
  • 2
    Your request is fine for elements, but be aware that treating XML attributes as having an order is contrary to the XML recommendation and [***should be avoided***](http://stackoverflow.com/a/19718720/290085). – kjhughes Nov 03 '14 at 15:55
  • Any chance you'd expand the question and tell us _why_ you want to do this? It may be there's a better way to achieve what you want. If it's just for the sheer intellectual pig iron of it then that's a reason too. – noonand Nov 03 '14 at 16:17
  • Forgo LINQ to XML and just use `XmlReader` to read the XML from beginning to end in one pass. – Michael Liu Nov 03 '14 at 20:16
  • Did you mean something like this:using (XmlReader reader = XmlReader.Create(new StringReader(xml))) { while(reader.Read()) { if (reader.NodeType == XmlNodeType.Attribute) { List.Add(XmlNodeType.Attribute); } if (reader.NodeType == XmlNodeType.Element) { list.Add(XmlNodeType.Element); } } } – Tee Nov 03 '14 at 20:34

1 Answers1

1

You could just recursively return the element name, attribute names, and child elements:

public IEnumerable<string> GetNodes(XElement xe)
{
   yield return xe.Name.ToString();
   foreach(XAttribute xa in xe.Attributes())
      yield return ("@"+xa.Name);
   foreach(XElement xee in xe.Elements())
      foreach(var s in GetNodes(xee))
          yield return s;

}

usage:

string xml = @"<Student number='2020'>
    <Subject>Comp</Subject>
    <Credintials>
    <Password>....</Password>
    </Credintials>
    <PersonalDetails age='30' height='2'/>
    </Student>";

XDocument x = XDocument.Parse(xml);
var nodes = GetNodes(x.Root);

result:

IEnumerable<String> (8 items)
------------------------------ 
Student 
@number 
Subject 
Credintials 
Password 
PersonalDetails 
@age 
@height 
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • I am now trying to get attributes & elements which have InnerText only using this solution, which yields the following list ie, @number,Subject,Password,@age,@height only.. That's the actual list i want. – Tee Nov 04 '14 at 08:26
  • @Tee should be a fairly simple `if` statement in the innermost `foreach`. If you can't figure it out ask another question. – D Stanley Nov 04 '14 at 14:22