xpath2.js is a DOM-agnostic open-source XPath 2.0 implementation in JavaScript. Execution engine operates using XML Schema 1.1 data types as prescribed by specification.
- Full XPath 2.0 language support
- Arbitrary tree structure querying with XPath 2.0 language via custom DOMAdapter
- Custom collation support (using StaticContext)
- Custom function support (using StaticContext)
- Variable injection (using DynamicContext)
npm install xpath2.jsThe simple API implementation lib/index.js provided for reference.
Its primary purpose is to demonstrate implementation classes wiring and a simple usable solution.
xpath.evaluate(expression,evaluationContext,staticContext,initialScope,DOMAdapter)| Name | Type | Required | Description |
|---|---|---|---|
expression | String | Required | xpath expression |
evaluationContext | Variant | Optional | evaluation context (document, for example) |
staticContext | StaticContext or Function | Optional | compilation context or namespace resolver |
initialScope | Object | Optional | JavaScript variable values map |
DOMAdapter | DOMAdapter | Optional | document object model adapter |
constxpath=require("xpath2.js");constresult=xpath.evaluate("1 to 5");console.log(result);// prints [ 1, 2, 3, 4, 5 ]constxpath=require("xpath2.js");constxmldom=require("xmldom");// You are free to use any DOM implementationconstdocument=newxmldom.DOMParser().parseFromString('<test>content</test>');constresult=xpath.evaluate("fn:string(/test/text())",document);console.log(result);// prints [ 'content' ]Evaluating expressions over documents that specify namespaces requires namespace resolver to be provided with the query. Take a note that namespace resolver is there to resolve prefixes found in XPath expressions, thus making use of prefixes in expressions scoped to the query, and not to the document.
A namespace resolver is a function that takes single argument String prefix and returns a namespace uri for it.
Exception XPST0081 will be thrown, should any of the prefixes used in expression are left unresolved.
constxpath=require("xpath2.js");constxmldom=require("xmldom");constdocument=newxmldom.DOMParser().parseFromString('<foo><a:bar xmlns:a="http://a">content</a:bar></foo>');constnamespaceResolver=function(prefix){if(prefix=="b")return"http://a";returnnull;};constresult=xpath.evaluate("fn:string(//b:bar/text())",document,namespaceResolver);console.log(result);// prints [ 'content' ]constxpath=require("xpath2.js");constresult=xpath.evaluate("$a + 0.2",null,null,{a: 0.1});console.log(result);// prints [ 0.3 ]constxpath=require("xpath2.js");constxmldom=require("xmldom");constdocument=newxmldom.DOMParser().parseFromString('<foo><a:bar xmlns:a="http://a">content</a:bar></foo>');constnamespaceResolver=function(prefix){if(prefix=="b")return"http://a";returnnull;};conststaticContext=xpath.createStaticContext(namespaceResolver);// Set default function namespace to the one of XPath functions, so "fn" prefix can be dropped in queriesstaticContext.defaultFunctionNamespace="http://www.w3.org/2005/xpath-functions";constdynamicContext=xpath.createDynamicContext(staticContext,document);constexpression=xpath.compile("string(//b:bar/text())",staticContext);constresult=xpath.execute(expression,dynamicContext);console.log(result);// prints [ 'content' ]Note! Dynamic context carries date/time obtained during its creation