16

Is there a simple way, to get all nodes from an xml document? I need every single node, childnode and so on, to check if they have certain attributes.

Or will I have to crawl through the document, asking for childnodes?

Nicolai
  • 2,835
  • 7
  • 42
  • 52
  • If you need to check for certain attributes, you don't need to go through _every node_ (text node, document node, comment node). Just go through every element node, or every attribute node (i.e. with LINQ or XSLT). Element nodes are the only node type with attributes. – Abel Sep 19 '11 at 07:20
  • How big is this document? Ie would it be worth optimizing? – H H Sep 19 '11 at 07:53
  • See the links [http://forums.asp.net/t/1285409.aspx/1](http://forums.asp.net/t/1285409.aspx/1) [http://www.developerfusion.com/article/4078/reading-storing-and-transforming-xml-data-in-net/5/](http://www.developerfusion.com/article/4078/reading-storing-and-transforming-xml-data-in-net/5/) [http://weblogs.asp.net/karan/archive/2010/04/29/parse-an-xml-file.aspx](http://weblogs.asp.net/karan/archive/2010/04/29/parse-an-xml-file.aspx) – Prasanth Sep 19 '11 at 07:15

8 Answers8

26

In LINQ to XML it's extremely easy:

XDocument doc = XDocument.Load("test.xml"); // Or whatever
var allElements = doc.Descendants();

So to find all elements with a particular attribute, for example:

var matchingElements = doc.Descendants()
                          .Where(x => x.Attribute("foo") != null);

That's assuming you wanted all elements. If you want all nodes (including text nodes etc, but not including attributes as separate nodes) you'd use DescendantNodes() instead.

EDIT: Namespaces in LINQ to XML are nice. You'd use:

var matchingElements = doc.Descendants()
                          .Where(x => x.Attribute(XNamespace.Xmlns + "aml") != null);

or for a different namespace:

XNamespace ns = "http://some.namespace.uri";

var matchingElements = doc.Descendants()
                          .Where(x => x.Attribute(ns + "foo") != null);
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Jeff: Do you mean in terms of using an indexer instead of a method call to get an attribute? If so, fixed. If not, I'm confused... – Jon Skeet Sep 19 '11 at 07:34
  • Yeah, that's what I meant. :) – Jeff Mercado Sep 19 '11 at 07:39
  • Excellent. Abit unrelated, but how would i check for attributes, which have a namespace in their name? Like: xmlns:aml? It says I can't have :'s in my attribute name. – Nicolai Sep 19 '11 at 07:50
7

In my opinion the simplest solution is using XPath. Also this works if you have .NET 2:

var testDoc = new XmlDocument();
testDoc.LoadXml(str);
var tmp = testDoc.SelectNodes("//*"); // match every element
BudBrot
  • 1,341
  • 2
  • 24
  • 44
7

see here: Iterating through all nodes in XML file

shortly:

 string xml = @"
    <parent>
      <child>
        <nested />
      </child>
      <child>
        <other>
        </other>
      </child>
    </parent>
    ";

  XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml));
  while (rdr.Read())
  {
    if (rdr.NodeType == XmlNodeType.Element)
    {
      Console.WriteLine(rdr.LocalName);
    }
  }
Community
  • 1
  • 1
Davide Piras
  • 43,984
  • 10
  • 98
  • 147
  • 3
    This method is generally very, very fast compared with XDocument and other DOM-like methods. – Abel Sep 19 '11 at 07:22
3

XDocument.Descendants will return you all the nodes in a flat enumerable.

Muhammad Hasan Khan
  • 34,648
  • 16
  • 88
  • 131
1

Check out LINQ to XML. That does what you need.

http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx

You can use the SelectMany extension for example.

But if you want to check the values you can just use LINQ to create where-statements.

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
Max
  • 1,068
  • 1
  • 10
  • 15
0
  protected void Page_Load(object sender, EventArgs e)
  {

            XmlDocument document = new XmlDocument();

            string xmlStr;
            using (var wc = new WebClient())
            {
                xmlStr = wc.DownloadString("test.xml");
            }

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(xmlStr);

            XmlNode xnod = xmlDoc.DocumentElement;

           AddWithChildren(xnod, 1);
 }
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
0
public void AddWithChildren(XmlNode xnod, Int32 intLevel) //,XmlDocument xmlDoc
    {  
        List<IEnumerable> item = new List<IEnumerable>();
        XmlNode xnodWorking;
        String strIndent = new string('-', 2 * intLevel);
        String strIndent1 = new string('@', 2 * intLevel);
        if (xnod.NodeType == XmlNodeType.Element)
        {
            item.Add(new ListXML(strIndent + xnod.Name, strIndent + xnod.Name, ""));
            XmlNamedNodeMap mapAttributes = xnod.Attributes;
            foreach (XmlNode xnodAttribute in mapAttributes)
            {
                item.Add(new ListXML(strIndent1 + xnodAttribute.Name, strIndent1 + xnodAttribute.Name, ""));
            }
            if (xnod.HasChildNodes)
            {
                xnodWorking = xnod.FirstChild;
                while (xnodWorking != null)
                {
                    AddWithChildren(xnodWorking, intLevel + 1);
                    xnodWorking = xnodWorking.NextSibling;
                }
            }
        }
    }
Luís Cruz
  • 14,780
  • 16
  • 68
  • 100
0
string AttrNameerr = "err";//find error code in xml
XmlReader rdr = XmlReader.Create(new stem.IO.StringReader(somesXMLtring));//somesXMLtring is xml in string variable we want to find attribute in.
while (rdr.Read())
{
    if (rdr.NodeType == XmlNodeType.Element)
    {
      //Found the new element, now check if the required attribute is present or not. if not, ignore, if yes then display the same
      string val = rdr.GetAttribute(AttrNameerr);//AttrNameerr is name of attribute we need to get value of which. here we are searching for error code stored as value of 'err' attribute

        if (val != null)
          textBox.Text = strResult = "error = " + rdr.GetAttribute(AttrNameerr);

    }
}
shree
  • 1
  • 2