Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Xpath and default namespaces

I have some JavaScript/Xpath which isn't working as I would expect. (available on jsfiddle) It would seem that I'm doing something wrong with an XML namespace, preventing me from querying for my elements by their node (tag) names.

If I try querying for all child nodes of the current node, I find the element myElement without problem:

    var xpathResult = xmlDoc.evaluate( "child::*", rootElement, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    var queryEl;
    if(queryEl = xpathResult.iterateNext()) {
        alert("child::* found element " + queryEl.nodeName);
    }
    else {
        alert("child::* found nothing!");
    }

... but if I specifically target the nodes with myElement node (tag) names I get no results:

    /* Now try getting only those children with nodeName `myElement` */
   xpathResult = xmlDoc.evaluate( "child::myElement", rootElement, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    var queryEl;
    if(queryEl = xpathResult.iterateNext()) {
        alert("child::myElement found element " + queryEl.nodeName);
    }
    else {
        alert("child::myElement found nothing!");
    }

What am I doing wrong?

like image 388
Richard JP Le Guen Avatar asked Mar 08 '12 17:03

Richard JP Le Guen


People also ask

What is XPath default namespace?

The Default NamespaceXPath treats the empty prefix as the null namespace. In other words, only prefixes mapped to namespaces can be used in XPath queries. This means that if you want to query against a namespace in an XML document, even if it is the default namespace, you need to define a prefix for it.

How does XPath handle namespace?

XPath queries are aware of namespaces in an XML document and can use namespace prefixes to qualify element and attribute names. Qualifying element and attribute names with a namespace prefix limits the nodes returned by an XPath query to only those nodes that belong to a specific namespace.

Can you use XPath in JavaScript?

This document describes the interface for using XPath in JavaScript internally, in extensions, and from websites. Mozilla implements a fair amount of the DOM 3 XPath, which means that XPath expressions can be run against both HTML and XML documents.

How do I find the XPath namespace?

There is no method to connect a namespace prefix to a namespace in XPath. The hosting library can provide these services. It is strongly advised that we take advantage of those features and create namespace prefixes that may be used to qualify XML element and attribute names as needed.


1 Answers

Try this as your resolver:

var nsResolver = (function (element) {
    var
      nsResolver = element.ownerDocument.createNSResolver(element),
      defaultNamespace = element.getAttribute('xmlns');

    return function (prefix) {
       return nsResolver.lookupNamespaceURI(prefix) || defaultNamespace;
    };
} (xmlDoc.documentElement));

You will also have to select the elements like this:

"child::default:myElement"
// where 'default' can be anything, as long as there is a namespace

Further reading:

  • https://developer.mozilla.org/en/DOM/document.createNSResolver
  • https://developer.mozilla.org/en/Introduction_to_using_XPath_in_JavaScript (=> Implementing a Default Namespace Resolver)
  • http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNSResolver-lookupNamespaceURI

Your fiddle: http://jsfiddle.net/chKZc/5/ (updated)

like image 161
Yoshi Avatar answered Sep 24 '22 22:09

Yoshi