4

I've loaded a XML document, and now I wish to run a XPath query to select a certain subset of the XML. The XML is

<?xml version="1.0"?>
<catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications with
      XML.</description>
   </book>
</catalog>

and the procedure goes something like

procedure RunXPathQuery(XML: IXMLDOMDocument2; Query: string);
begin

  XML.setProperty('SelectionLanguage', 'XPath');

  NodeListResult := XML.documentElement.selectNodes(Query));

  ShowMessage('Found (' + IntToStr(NodeListResult.length) + ') nodes.');

end;

Problem is: when I run the XPath query '/catalog' for the above XML, it returns (as expected) a nodelist of 1 element. However, if I remove :xsi from <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> and re-run the query, the nodelist returned is empty. If I remove the entire 'xmlns'-attribute, the resulting nodelist has, once again, 1 element.

So my question is this: what can I do to remedy this, i.e. how do I make MSXML return the correct number of instances (when running a XPath query), regardless of the namespace (or other attributes)?

Thanks!

conciliator
  • 6,078
  • 6
  • 41
  • 66
  • Either I'm reading this (http://support.microsoft.com/kb/288147) totally wrong, or its impossible to use a default namespace with XPath for certain versions of MSXML. Unfortunately, I'm using MSXML v6.0, so this shouldn't affect me. Anyone had similar experiences? – conciliator Oct 05 '09 at 13:09

4 Answers4

3

See this link!

When you use <catalog xmlns='http://www.w3.org/2001/XMLSchema-instance'> then the whole node will be moved to a different (default) namespace. Your XPath isn't looking inside this other namespace so it can't find any data. With <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> you're just declaring xsi as a different namespace. This would be a different namespace than the default namespace.

I can't test it right now but adding something like this might help:

XML.setProperty('SelectionNamespaces', 'xmlns=''http://www.w3.org/2001/XMLSchema-instance''');

Or maybe it doesn't. As I said, I can't test it right now.

johnny
  • 657
  • 7
  • 18
Wim ten Brink
  • 25,901
  • 20
  • 83
  • 149
  • Thanks Workshop Alex! That makes a lot of sense. Unfortunately, it doesn't seem to do the trick (yet), but I'll play around with it a little more. – conciliator Oct 05 '09 at 11:48
2

Figured it out. It seems that my problem has been described here and here (and most likely a zillion other places, too).

The query /*[local-name()='catalog'] works for me.

Community
  • 1
  • 1
conciliator
  • 6,078
  • 6
  • 41
  • 66
1

Use:

document.setProperty('SelectionNamespaces', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
Stuart Grassie
  • 3,043
  • 1
  • 27
  • 36
0
/*[local-name()='catalog'] 

is a solution to your question. But why would you want to ignore namespaces? They have been introduced to express something, e.g. to distinguish different types of catalogs. With your query, you can now select the content of any catalog in the world, but I assume you can only handle books. What will happen if you get a catalog of screws or cars instead?

The mentioned things about the prefix (xsi) is correct. If you remove the prefix, all elements are in that namespace (called default namespace then). But you can still deal with it.

In your code, give the namespace a prefix anyway. It needn't even match the original prefix:

XML.setProperty('SelectionNamespaces', "xmlns:xyz='http://www.w3.org/2001/XMLSchema-instance'"); 

The second thing is to adapt the XPath query. It must then be

/xyz:catalog

The original XML only declares the xsi namespace, but never makes use of it. In this case, you can remove it completely. If you want to use the namespace and you want it with prefixes, then rewrite your XML to

<?xml version="1.0"?>
<xsi:catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
  <xsi:book id="bk101">
    <xsi:author>Gambardella, Matthew</xsi:author>
    <xsi:title>XML Developer's Guide</xsi:title>
    <xsi:genre>Computer</xsi:genre>
    <xsi:price>44.95</xsi:price>
    <xsi:publish_date>2000-10-01</xsi:publish_date>  
    <xsi:description>An in-depth look at creating applications with 
    XML.</xsi:description>
 </xsi:book>
</xsi:catalog>
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222