diff --git a/src/providers/XPath.ts b/src/providers/XPath.ts index 168deec..fd54e84 100644 --- a/src/providers/XPath.ts +++ b/src/providers/XPath.ts @@ -2,7 +2,7 @@ import * as vsc from 'vscode'; import * as ext from '../Extension'; -import { XPathEvaluator } from '../services/XPathEvaluator'; +import { XPathEvaluator, EvaluatorResult, EvaluatorResultType } from '../services/XPathEvaluator'; const CFG_SECTION: string = 'xmlTools'; const CFG_PERSIST_QUERY: string = 'persistXPathQuery'; @@ -59,12 +59,11 @@ export class XPathFeatureProvider { // run the query let xml: string = editor.document.getText(); - let nodes: Node[]; + let evalResult: EvaluatorResult; try { - nodes = XPathEvaluator.evaluate(query, xml, ignoreDefaultNamespace); + evalResult = XPathEvaluator.evaluate(query, xml, ignoreDefaultNamespace); } - catch (error) { console.error(error); vsc.window.showErrorMessage(`Something went wrong while evaluating the XPath: ${error}`); @@ -78,10 +77,13 @@ export class XPathFeatureProvider { outputChannel.appendLine(`XPath Query: ${query}`); outputChannel.append('\n'); - nodes.forEach((node: XmlNode) => { - outputChannel.appendLine(`[Line ${node.lineNumber}] ${node.localName}: ${node.textContent}`); - }); - + if (evalResult.type === EvaluatorResultType.NODE_COLLECTION) { + (evalResult.result as Node[]).forEach((node: XmlNode) => { + outputChannel.appendLine(`[Line ${node.lineNumber}] ${node.localName}: ${node.textContent}`); + }); + } else { + outputChannel.appendLine(`[Result]: ${evalResult.result}`); + } outputChannel.show(vsc.ViewColumn.Three); // if persistence is enabled, save the query for later diff --git a/src/services/XPathEvaluator.ts b/src/services/XPathEvaluator.ts index 3bc77a2..50979b2 100644 --- a/src/services/XPathEvaluator.ts +++ b/src/services/XPathEvaluator.ts @@ -4,8 +4,18 @@ import * as xpath from 'xpath'; let DOMParser = require('xmldom').DOMParser; +export class EvaluatorResult { + type: EvaluatorResultType; + result: Node[]|number|string|boolean; +} + +export class EvaluatorResultType { + static SCALAR_TYPE: number = 0; + static NODE_COLLECTION: number = 1; +} + export class XPathEvaluator { - static evaluate(query: string, xml: string, ignoreDefaultNamespace: boolean): Node[] { + static evaluate(query: string, xml: string, ignoreDefaultNamespace: boolean): EvaluatorResult { if (ignoreDefaultNamespace) { xml = xml.replace(/xmlns=".+"/g, (match: string) => { return match.replace(/xmlns/g, 'xmlns:default'); @@ -17,14 +27,39 @@ export class XPathEvaluator { let xdoc: Document = new DOMParser().parseFromString(xml, 'text/xml'); let resolver: xpath.XPathNSResolver = xpath.createNSResolver(xdoc); - let expression: xpath.XPathExpression = xpath.createExpression(query, resolver); - let result: xpath.XPathResult = expression.evaluate(xdoc, xpath.XPathResult.ORDERED_NODE_ITERATOR_TYPE); + let result: xpath.XPathResult = xpath.evaluate( + query, // xpathExpression + xdoc, // contextNode + resolver, // namespaceResolver + xpath.XPathResult.ANY_TYPE, // resultType + null // result + ) + + let evalResult = new EvaluatorResult(); + evalResult.type = EvaluatorResultType.SCALAR_TYPE; - let node: Node; - while (node = result.iterateNext()) { - nodes.push(node); + switch(result.resultType) { + case xpath.XPathResult.NUMBER_TYPE: + evalResult.result = result.numberValue; + break; + case xpath.XPathResult.STRING_TYPE: + evalResult.result = result.stringValue; + break; + case xpath.XPathResult.BOOLEAN_TYPE: + evalResult.result = result.booleanValue; + break; + case xpath.XPathResult.UNORDERED_NODE_ITERATOR_TYPE: + case xpath.XPathResult.ORDERED_NODE_ITERATOR_TYPE: + evalResult.result = result.booleanValue; + let node: Node; + while (node = result.iterateNext()) { + nodes.push(node); + } + evalResult.result = nodes; + evalResult.type = EvaluatorResultType.NODE_COLLECTION; + break; } - - return nodes; + + return evalResult; } } \ No newline at end of file