5

Been looking around for an answer and cant find anything - Im quite new so maybe Im not hitting up the right key words?

This is a sample of the XML I am working with

<database>
<book>
<title>A</title>
<author>
  <name>1</name>
</author>
</book>
<book>
<title>B</title>
<author>
  <name>2</name>
</author>
<author>
  <name>3</name>
</author>
<author>
  <name>4</name>
</author>
<author>
  <name>5</name>
</author>
</book>
</database>

Im trying to use C# XMLDocument to grab for book A author 1 and then for book B author 1, 2, 3, 4, 5

So far the code I am working with is cycling through ALL the authors so I am getting book A author 1, 2, 3, 4, 5

The code I have so far is as follows roughly

XmlDocument doc = new XmlDocument();
doc.Load("myxmlfile");
XmlNode root = doc.SelectSingleNode("database");
XmlNodeList nodelist = root.SelectNodes("book");

foreach (XmlNode n in nodelist)
        {

XmlNodeList authors = root.SelectNodes(".//author");
book.authorstring = "";
foreach (XmlNode author in authors)
       {
       book.authorstring = book.authorstring+author.SelectSingleNode("name").InnerText + ", ";
       }
}

I read some where that if I use " . " before the " // " that it would "anchor" to the current node but it doesnt seem to be working and is cycling through all the nodes

What am I doing wrong or missing?

chilly8063
  • 117
  • 2
  • 3
  • 8

3 Answers3

7

If i understand you correctly your error is in this line :

XmlNodeList authors = root.SelectNodes(".//author");

it should be

XmlNodeList authors = n.SelectNodes(".//author");
Kristof
  • 3,267
  • 1
  • 20
  • 30
3

For future readers, I came across this article and I had forgot to add a . to my xPath.

I.e. (this was powershell but that does not matter),

This was wrong and returned the first node found from the rootnode:

$descriptionNode = $someNode.SelectSingleNode("//Description")

And this was right and returned the first node as child of the node:

$descriptionNode = $someNode.SelectSingleNode(".//Description")

Which is ofcourse because // would query anywhere, and ./ would query relatively. Quite a clear explanation, but it was easy to miss and it took some time to find.

Handy cheatsheet: https://devhints.io/xpath

sommmen
  • 6,570
  • 2
  • 30
  • 51
1

Use linq2XML..it is simple to use

XElement doc=XElement.Load("yourXML.xml");

var lstBooks=doc.Descendants("book").Select(x=>
new
{
    name=x.Element("title").Value,
    authors=x.Elements("author").Select(y=>y.Element("name").Value)
}
);

lstBooks now contains all the required data

You can now do this

foreach(var book in lstBooks)
{
book.name;//Name of the book
    foreach(var author in book)
    {
        author;//name of the author
    }
}
Anirudha
  • 32,393
  • 7
  • 68
  • 89