1
votes
<?xml version="1.0"?>

-<bookstore>            
        <book > 
            <title>aaaa</title> 
            -<author > 
                <first-name>firts</first-name> 
                <last-name>last</last-name> 
            </author> 
            <price>8.23</price> 
            <otherbooks>
                    <book > 
                        <title>bbb</title>      
                        <price>18.23</price> 
                    </book>     
                    <book > 
                        <title>ccc</title>      
                        <price>11.22</price> 
                    </book>     
            </otherbooks>
        </book> 
</bookstore>

I would like to select all books at different levels and then display information about each one (author, title and price). At the moment code would also display otherbooks for first book. What would be the best way of displaying only required information. I need to use XPath.

xPathDoc = new XPathDocument(filePath);
xPathNavigator = xPathDoc.CreateNavigator();
XPathNodeIterator xPathIterator = xPathNavigator.Select("/bookstore//book");
foreach (XPathNavigator navigator in xPathIterator)
{
     XPathNavigator clone = navigator.Clone();
     clone.MoveToFirstChild();

     Console.WriteLine(clone.Name + " : " + clone.Value);
     while (clone.MoveToNext())
     {
         Console.Write(clone.Name + " : " + clone.Value + " | ");
     }
} 
2
What do you mean with "at different levels"? Your selector retrieves <book /> elements at all levels below <bookstore />. Don't you want book/otherbooks/book to be selected? - hielsnoppe
I want all books to be selected but then I would like to display info about each single book at the moment first book also include <otherbooks> info and then <otherbooks> are displayed again on their own - witpo
So is your current solution broken, or do you want to improve it? I think your current selector should achieve what you describe. - hielsnoppe
Selecting all books is working ok. I have problem how to display information about each book when iterating with use of XPathNavigator. My solution is going too deep and is display <otherbooks> for the first book when it should only display (author, title and price) - witpo
If you can think of a better way of doing it with use of XPath please let me know. - witpo

2 Answers

1
votes

If you are open to try Linq To Xml :

var xDoc = XDocument.Parse(xml); //or XDocument.Load(filename)
var books = xDoc.Root.Elements("book")
            .Select(b => new
            {
                Author = b.Element("author").Element("first-name").Value + " " +
                            b.Element("author").Element("last-name").Value,
                Books = b.Descendants("book")
                            .Select(x => new 
                            {
                                Title = x.Element("title").Value,
                                Price = (decimal)x.Element("price"),
                            })
                            .Concat(new[] { new { Title = b.Element("title").Value, 
                                                Price = (decimal)b.Element("price") } 
                                        })
                            .ToList()

            })
            .ToList();
1
votes

The double slash (//) is specifying all descendents, not just the immediate one. How about

/bookstore/book 

? That will get you the top level book only.