Search code examples
c#xmlxpath

Xml decendants for a Xml node


Here is a simplified mxl structure 'xml',

<store>

<book_1>
   <author_1><name>Alice</name><age>30</age></author_1>
   <author_2><name>Bob</name><age>31</age></author_2>
<book_1>
   <author_1><name>Charley</name><age>29</age></author_1>
   <author_2><name>Dory</name><age>25</age></author_2> 
<book_1>    
</store>

Here is what I tried;

 XmlDocument submission = new XmlDocument();
   submission.LoadXml(xml);
    var bookNodes = submission.SelectNodes("//*[starts-with(local-name(),'book_')]");

This gives me a list of books.

 foreach (XmlNode book in bookNodes)
  {
    //I want to do something like to find book authors for the book in context e.g. for the first book I just want nodes for Alice and Bob.
   // var bookAuthors = book.SelectNodes("decendants::[starts-with(local-name(),'author_')"); 

  }

How can I just do a starts with to check on decendent elements?

EDIT: Seems like it's a typo...

var bookAuthors = book.SelectNodes("descendant::*[starts-with(local-name(),'MeritCriterion_')]");


Solution

  • You can access your descendant nodes by using the following XPath syntax:

    XmlDocument submission = new XmlDocument();
    submission.LoadXml(xml);
    
    var bookNodes = submission.SelectNodes("//*[starts-with(local-name(),'book_')]");
    
    foreach (XmlNode book in bookNodes)
    {
        var author = book.SelectNodes("descendant::*[starts-with(local-name(),'author_')]");
    
        foreach (XmlNode authorInfo in author)
        {
            Console.WriteLine(authorInfo .InnerText);
        }
    }
    

    In short, you need to access descendant::(all)[starts-with] or else you're just trying to access no descendant in your XPath. :)