Xpath is rarely used by us now because JSON is very popular now. However, in the era when XML was a data exchange format, Xpath played a very important position when we randomly accessed large XML document structures. Perhaps many people have not noticed that the interface specified by DOM Level 3 XPath has been implemented by Firefox, Safari, Chrome, and Opera. The core interface they implement is XPathEvaluator, which contains some methods that can work with xpath expressions. The most important method is evaluate(), which can accept five parameters 1.xpath query string 2. Indicate which node the xpath query string should start from 3. Namespace parser (introduced later) 4. Returned result type 5. The returned result should be added to that object (seldom used, because the result is mainly returned through evaluate()).
There are mainly 10 different return types. Each represents a constant of the XPathResult object.
After so much introduction, how should we use these APIs to operate?
The information returned by the evaluate() function depends entirely on the requested result type.
In order to execute xpath query, you need to use the XPathEvaluator object. You can generate a new object or use the built-in object. If you generate a new object, you need to initialize the XPathEvaluator.
var evaluator = new XPathEvaluator(); //Get the first div var result = evaluator.evaluate("//div", document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); alert("First div ID is " + result.singleNodeValue.id);In Firefox, Safari, Chrome, and Opera, all document instances implement the XPathEvaluator interface. In this way, if a query is executed in an HTML page, we can use document.evaluate(). If the XML document is obtained through XMLHttpRequest or other mechanisms, the evaluate() method can also be used, for example:
//get first div var result = document.evaluate("//div", document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); alert("First div ID is " + result.singleNodeValue.id);The following are two ways to return multiple nodes, let’s take a look at the examples first:
//get all divs - iterator style var result = document.evaluate("//div", document.documentElement, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); if (result){ var node = result.iterateNext(); while(node) { alert(node.id); node = node.iterateNext(); } } //get all divs - SNAPSHOT style var result = document.evaluate("//div", document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (result){ for (var i=0, len=result.snapshotLength; i < len; i++) { alert(result.snapshotItem(i).id); } }Namespace
If you just use xpath to query in html documents, the namespace parser parameter in evaluate() is generally null. If you tend to use xpath to query in xml documents containing namespace, then you should learn how to create and use namespace parser.
In addition to the default namespace, each namespace URI is mapped to a specified prefix. Each namespace resolver is used to map the namespace prefix and namespace uri for the xpath engine. There are two ways to generate a namespace resolver. The first is as follows: create a method that accepts a namespace prefix as a parameter, and then returns the corresponding url, as follows:
function resolver(prefix){ switch(prefix){ case "wrox": return "http://www.wrox.com/"; case "ncz": return "http://www.nczonline.net/"; default: return "http://www.yahoo.com/"; } }The second type uses a node containing namespace information to generate a namespace resolver.
<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> <wrox:book>Professional JavaScript</book> </books>
The <books> element contains all namespace information. You can pass the reference to this node to the createNSResovler() method of the XPathEvaluator object, and then you can automatically get a namespace resolver.
like:
var evaluator = new XPathEvaluator(); var resolver = evaluator.createNSResolver(xmldoc.documentElement);
Using any of the above methods, it is easy to query in an XML document containing the namespace.
var evaluator = new XPathEvaluator(); var resolver = evaluator.createNSResolver(xmldoc.documentElement); var result = evaluator.evaluate("wrox:book", xmldoc.documentElement, resolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null); if (result){ alert(result.singleNodeValue.firstChild.nodeValue); }Note: If you execute a query in an XML document containing a namespace and do not provide a namespace parser, an error will occur.
Support for xpath in IE browser
IE8 has not yet implemented the interface defined in DOM Level 3 XPath, but it also has certain support for xpath. The xpath function in IE is mainly available for xml documents and is not available for document objects.
How to generate xml documents in IE:
function createDocument(){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument"]; for (var i=0,len=versions.length; i < len; i++){ try { var xmldom = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xmldom; } catch (ex){ //skip } } } return new ActiveXObject(arguments.callee.activeXString); }After generating the document object, you can use the loadXML() method to load the content:
var xmldoc = createDocument(); xmldoc.loadXML("");The second method generates an XML object through the XMLHttRequest object.
var xhr = new XMLHttpRequest(), xmldoc; xhr.open("get", "data.xml", true); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if (xhr.status >= 200 && xhr.status < 300){ xmldoc = xhr.responseXML; } }; xhr.send(null);The third method is to use the <xml> tag. Microsoft calls this method xml data island, as follows:
<xml id="myXML" src="data.xml"></xml>
Then:
var xmldoc = document.getElementById("myXML").XMLDocument;XPath support:
There are two built-in methods for supporting xpath in xml document objects in ie:
selectSingleNode() and selectNodes(), each method accepts an xpath expression as a parameter, and then puts back the first matching node and all matching nodes respectively.
Namespace support:
for
<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> <wrox:book>Professional JavaScript</book>
</books>For this xml document, we should use the following method to query, that is, first use setProperty() to set the namespace of the xml document.
xmldoc.setProperty("SelectionNamespaces", "xmlns:wrox='http://www.wrox.com/' xmlns='http://www.amazon.com/'");var book = xmldoc.documentElement.selectSingleNode("wrox:book");