6

I am trying to read from an ncx file (i.e. xml file) using XElement:

XElement foundNode = ncx.Descendants("navPoint").Where(r => r.Attribute("class").Value == "chapter").FirstOrDefault();

As a result, foundNode is null because ncx.Descendants("navPoint") returns an empty enumeration. But the data is there:

<?xml version='1.0' encoding='utf-8'?>
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="en">
  <head>
    <meta content="8eab2efe-d584-478a-8c73-1304d2ae98fa" name="dtb:uid"/>
    <meta content="3" name="dtb:depth"/>
    <meta content="calibre (0.8.12)" name="dtb:generator"/>
    <meta content="0" name="dtb:totalPageCount"/>
    <meta content="0" name="dtb:maxPageNumber"/>
  </head>
  <docTitle>
    <text>Fine</text>
  </docTitle>
  <navMap>
    <navPoint class="chapter" id="27665f37-ecf5-4934-a044-4f77152e54d9" playOrder="1">
      <navLabel>
        <text>I. BLIND</text>
      </navLabel>
      <content src="Fine_split_003.html"/>

Could you please explain what is wrong here? Thanks.

dpreznik
  • 247
  • 5
  • 18

2 Answers2

14

You need to take namespace in XML into account:

XDocument ncx = XDocument.Load("file.xml");
XNamespace df = ncx.Root.Name.Namespace;
XElement foundNode = ncx.Descendants(df + "navPoint").Where(r => r.Attribute("class").Value == "chapter").FirstOrDefault();
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thanks, it worked. May I ask when namespace is needed? Because in the example I used (http://msmvps.com/blogs/deborahk/archive/2010/01/31/finding-a-node-in-an-xml-string.aspx) it is not mentioned. – dpreznik Sep 21 '11 at 17:03
  • Well as soon as the XML has e.g. `xmlns="http://example.com/foo"` or `xmlns:pf="http://example.com/bar"` your LINQ to XML code that wants to select any elements (or also attributes in the second case) in such a namespace you should use an `XNamespace` object: http://msdn.microsoft.com/en-us/library/bb387093.aspx – Martin Honnen Sep 21 '11 at 17:23
  • thanks. I wonder why now I get the same problem:string title = foundNode.Elements("text").FirstOrDefault().Value; Now adding namespace doesn't help... unless I added a wrong namespace. – dpreznik Sep 21 '11 at 17:47
3

You can also strip out namespaces or refer to elements without using the namespace by using the XElement.Name.LocalName property: Examples here

Community
  • 1
  • 1
Trygve
  • 2,445
  • 1
  • 19
  • 23