tags:

views:

204

answers:

3

I have an XML document which is confounding me. I'd like to (to start) pull all of the document nodes (/database/document), but it only works if I remove all of the attributes on the database element. Specifically the xmlns tag causes an xpath query for /database/document to return nothing - remove it, and it works.

xmlns="http://www.lotus.com/dxl"

I take it this has to do with XML namespaces. What is it doing, and more to the point, how do I make it stop? I just want to parse the document for data.

<?xml version="1.0" encoding="utf-8"?>
<database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.lotus.com/dxl xmlschemas/domino_7_0_3.xsd"
          xmlns="http://www.lotus.com/dxl"
          version="7.0"
          maintenanceversion="3.0"
          path="C:\LotusXML\test1.nsf"
          title="test1">
  <databaseinfo numberofdocuments="3">
    <datamodified>
      <datetime dst="true">20090812T142141,48-04</datetime>
    </datamodified>
    <designmodified>
      <datetime dst="true">20090812T154850,91-04</datetime>
    </designmodified>
  </databaseinfo>
  <document form="NameAddress">
    <noteinfo noteid="8fa" unid="x" sequence="2">
      <created>
        <datetime dst="true">20090812T130308,71-04</datetime>
      </created>
      <modified>
        <datetime dst="true">20090812T142049,36-04</datetime>
      </modified>
      <revised>
        <datetime dst="true">20090812T142049,35-04</datetime>
      </revised>
      <lastaccessed>
        <datetime dst="true">20090812T142049,35-04</datetime>
      </lastaccessed>
      <addedtofile>
        <datetime dst="true">20090812T130321,57-04</datetime>
      </addedtofile>
    </noteinfo>
    <updatedby>
      <name>MOOSE</name>
    </updatedby>
    <revisions>
      <datetime dst="true">20090812T130321,57-04</datetime>
    </revisions>
    <item name="Name">
      <text>joe</text>
    </item>
    <item name="OtherName">
      <text>dave</text>
    </item>
    <item name="Address">
      <text>here at home</text>
    </item>
    <item name="PictureHere">
      <richtext>
        <pardef id="1" />
        <par def="1">
        </par>
        <par def="1" />
      </richtext>
    </item>
  </document>
  <document form="NameAddress">
    <noteinfo noteid="8fe" unid="x" sequence="2">
      <created>
        <datetime dst="true">20090812T130324,59-04</datetime>
      </created>
      <modified>
        <datetime dst="true">20090812T142116,95-04</datetime>
      </modified>
      <revised>
        <datetime dst="true">20090812T142116,94-04</datetime>
      </revised>
      <lastaccessed>
        <datetime dst="true">20090812T142116,94-04</datetime>
      </lastaccessed>
      <addedtofile>
        <datetime dst="true">20090812T130333,90-04</datetime>
      </addedtofile>
    </noteinfo>
    <updatedby>
      <name>MOOSE</name>
    </updatedby>
    <revisions>
      <datetime dst="true">20090812T130333,90-04</datetime>
    </revisions>
    <item name="Name">
      <text>fred</text>
    </item>
    <item name="OtherName">
      <text>wilma</text>
    </item>
    <item name="Address">
      <text>bedrock</text>
    </item>
    <item name="PictureHere">
      <richtext>
        <pardef id="1" />
        <par def="1">
        </par>
        <par def="1" />
      </richtext>
    </item>
  </document>
  <document form="NameAddress">
    <noteinfo noteid="902" unid="x" sequence="2">
      <created>
        <datetime dst="true">20090812T130337,09-04</datetime>
      </created>
      <modified>
        <datetime dst="true">20090812T142141,48-04</datetime>
      </modified>
      <revised>
        <datetime dst="true">20090812T142141,47-04</datetime>
      </revised>
      <lastaccessed>
        <datetime dst="true">20090812T142141,47-04</datetime>
      </lastaccessed>
      <addedtofile>
        <datetime dst="true">20090812T130350,20-04</datetime>
      </addedtofile>
    </noteinfo>
    <updatedby>
      <name>MOOSE</name>
    </updatedby>
    <revisions>
      <datetime dst="true">20090812T130350,20-04</datetime>
    </revisions>
    <item name="Name">
      <text>julie</text>
    </item>
    <item name="OtherName">
      <text>mccarthy</text>
    </item>
    <item name="Address">
      <text>the pen</text>
    </item>
    <item name="PictureHere">
      <richtext>
        <pardef id="1" />
        <par def="1">
        </par>
        <par def="1" />
      </richtext>
    </item>
  </document>
</database>
+2  A: 

When there is an XML namespace defined, each element needs to preceded by it for it to be correctly recognized.

If you were to use LINQ to XML to read in this data it would look something like this:

XDocument xdoc = XDocument.Load("file.xml");
XNamespace ns = "http://www.lotus.com/dxl";
var documents = xdoc.Descendants(ns + "document");

XML namespaces are similar in concept to C# namespaces (or any other language that supports it). If you define a class inside a namespace, you wouldn't be able to access it without first specifying the namespace (this is what using statements do for you).

Jason Miesionczek
So what's the valid xPath expression that will find the three documents?
quillbreaker
After defining the namespace/ns:database/ns:documentWould do it, but Jason's LINQ to XML answer will resolve to the same (or functionally equivalent) XPath query for you
MattH
in the above example, the 'documents' variable would contain a collection of document XElements. Which you could iterate through and extract the data you need through additional LINQ queries.
Jason Miesionczek
+1  A: 

You need to specify the element by their full name, including the namespace. The easy way to do this is to define the appropriate XNamespace and prepend it to the element name.

XDocument myDoc;
XNamespace ns = "http://www.lotus.com/dxl";
XElement myElem = myDoc.Element(ns + "ElementName");

See MSDN for more information.

Rik
+7  A: 

The xmlns="http://www.lotus.com/dxl" sets a default namespace for contained nodes. It means that /database/document is really /{http://www.lotus.com/dxl}:database/{http://www.lotus.com/dxl}:document. Your XPath query will need to include the namespace:

XmlDocument doc = new XmlDocument();
doc.Load(fileName);
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("tns", "http://www.lotus.com/dxl");
var documents = doc.SelectNodes("/tns:database/tns:document", ns);
John Saunders
I am told the fifth line needs to read var documents = doc.SelectNodes("/tns:database/tns:document",ns);
quillbreaker
Fixed it. thanks.
John Saunders