├── .gitattributes ├── resources ├── xslt │ ├── test │ │ ├── xslt-out │ │ │ └── eval-result.json │ │ ├── test.xml │ │ └── test-eval.xsl │ └── xpath-eval-to-json.xsl └── xslt-sef │ └── xpath-eval-to-json.sef.json ├── .gitignore ├── button.png ├── json-output.png ├── cell-variables.png ├── empty-notebook.png ├── xpath-notebook.jpg ├── html-output-cell.png ├── notebooks ├── .DS_Store ├── demo │ ├── notebookVariables │ │ └── countries.xbook │ ├── dataCompare │ │ ├── analyse-compare.xbook │ │ └── compare-result.xml │ └── demo.xbook ├── jupyter │ └── test.ipynb ├── gdpbycountry │ ├── gdpByCountry.xml │ └── gdpByCountry.xbook └── introduction │ └── xpath-notebook.xbook ├── consolidated-button.png ├── deltaxigniaLogoSmall.png ├── notebook-vscode-small.png ├── xpath-notebook-small.png ├── src ├── CHANGELOG.md ├── dummy.js ├── cellStatusProvider.ts ├── xbookSerializer.ts ├── jsonDefinitionProvider.ts ├── extensionData.ts ├── extension.ts ├── linkProvider.ts ├── htmlTables.ts ├── jsonHoverProvider.ts ├── xpathResultTokenProvider.ts ├── xbookController.ts └── nodeKernel.ts ├── .vscodeignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.xbook linguist-language=JSON -------------------------------------------------------------------------------- /resources/xslt/test/xslt-out/eval-result.json: -------------------------------------------------------------------------------- 1 | {"node":[]} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | out/**/* 3 | *.vsix 4 | **/.DS_Store 5 | -------------------------------------------------------------------------------- /button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/button.png -------------------------------------------------------------------------------- /json-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/json-output.png -------------------------------------------------------------------------------- /cell-variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/cell-variables.png -------------------------------------------------------------------------------- /empty-notebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/empty-notebook.png -------------------------------------------------------------------------------- /xpath-notebook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/xpath-notebook.jpg -------------------------------------------------------------------------------- /html-output-cell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/html-output-cell.png -------------------------------------------------------------------------------- /notebooks/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/notebooks/.DS_Store -------------------------------------------------------------------------------- /consolidated-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/consolidated-button.png -------------------------------------------------------------------------------- /deltaxigniaLogoSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/deltaxigniaLogoSmall.png -------------------------------------------------------------------------------- /notebook-vscode-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/notebook-vscode-small.png -------------------------------------------------------------------------------- /xpath-notebook-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeltaXML/vscode-xpath-notebook/HEAD/xpath-notebook-small.png -------------------------------------------------------------------------------- /resources/xslt/test/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "xslt-xpath for vscode" extension are documented in the project wiki, see: [Release Notes](https://github.com/DeltaXML/vscode-xpath-notebook/wiki/Release-Notes). -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/test/** 4 | out/**/*.map 5 | out/**/*.spec.js 6 | src/** 7 | notebooks/** 8 | .gitignore 9 | tsconfig.json 10 | jest.config.js 11 | tslint.json 12 | *.vsix 13 | resources/xslt/** -------------------------------------------------------------------------------- /notebooks/demo/notebookVariables/countries.xbook: -------------------------------------------------------------------------------- 1 | [{"kind":2,"language":"xpath","value":"variable = c% /countries/country"},{"kind":2,"language":"xpath","value":"variable = gdp% $c/gdp-estimates"},{"kind":2,"language":"xpath","value":"$gdp/estimate/@year"},{"kind":2,"language":"xpath","value":""}] -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "args": [ 9 | "--extensionDevelopmentPath=${workspaceFolder}", 10 | "--enable-proposed-api", 11 | "deltaxml.xpath-notebook" 12 | ], 13 | "outFiles": [ 14 | "${workspaceFolder}/out/**/*.js" 15 | ], 16 | "preLaunchTask": "${defaultBuildTask}" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2021", 8 | "DOM", 9 | ], 10 | "types": [ 11 | "vscode-notebook-renderer", 12 | "node" 13 | ], 14 | "sourceMap": true, 15 | "rootDir": "src", 16 | "strict": true, 17 | "noUnusedParameters": true, 18 | "forceConsistentCasingInFileNames": true 19 | }, 20 | "exclude": [ 21 | "node_modules", 22 | ".vscode-test" 23 | ] 24 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } -------------------------------------------------------------------------------- /notebooks/jupyter/test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "source": [], 7 | "outputs": [], 8 | "metadata": {} 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "source": [ 14 | "" 15 | ], 16 | "outputs": [], 17 | "metadata": {} 18 | } 19 | ], 20 | "metadata": { 21 | "orig_nbformat": 4, 22 | "language_info": { 23 | "name": "plaintext" 24 | } 25 | }, 26 | "nbformat": 4, 27 | "nbformat_minor": 2 28 | } -------------------------------------------------------------------------------- /src/dummy.js: -------------------------------------------------------------------------------- 1 | 2 | class GlobalVariables { 3 | variables = {}; 4 | setVariable = (name, value) => { 5 | this.variables[name] = value; 6 | } 7 | getVariables = () => { 8 | return this.variables; 9 | } 10 | getVariable = (name) => { 11 | return this.variables[name]; 12 | } 13 | } 14 | 15 | const variables = {}; 16 | const setVariable = (name, value) => { 17 | variables[name] = value; 18 | } 19 | const getVariables = () => { 20 | return variables; 21 | } 22 | const getVariable = (name) => { 23 | return variables[name]; 24 | } 25 | let prevResult = []; -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "watch", 7 | "problemMatcher": "$tsc-watch", 8 | "isBackground": true, 9 | "presentation": { 10 | "reveal": "never" 11 | }, 12 | "group": { 13 | "kind": "build", 14 | "isDefault": true 15 | } 16 | }, 17 | { 18 | "type": "xslt-js", 19 | "label": "TEST JSON TO XML", 20 | "xsltFile": "resources/xslt/test-eval.xsl", 21 | "xmlSource": "resources/xslt/test-eval.xsl", 22 | "initialTemplate": "main", 23 | "resultPath": "resources/xslt-out/eval-result.json", 24 | "group": { 25 | "kind": "build" 26 | }, 27 | "problemMatcher": [ 28 | "$saxon-xslt-js" 29 | ] 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 DeltaXML Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /notebooks/demo/dataCompare/analyse-compare.xbook: -------------------------------------------------------------------------------- 1 | [{"kind":1,"language":"markdown","value":"# Introducing XPath Notebooks"},{"kind":1,"language":"markdown","value":"## XML Compare Sample\nDeclare a function that returns the value for the version specified by `$delta` of leaf-element `$element`"},{"kind":2,"language":"xpath","value":"variable = version %\nfunction($element, $delta) { \n string(($element/deltaxml:textGroup/deltaxml:text[@deltaxml:deltaV2 eq $delta], $element)[1])\n}"},{"kind":1,"language":"markdown","value":"For each each `person` element, get the values (using `$version` function defined in previous cell) for the child leaf-node elements."},{"kind":2,"language":"xpath","value":"for $person in /contacts/person return (\n for $d in $person//*[not(self::deltaxml:*) and empty(* except deltaxml:*)] return\n map {\n 'Field': name($d),\n 'OK': (if ($d/deltaxml:*) then '✘' else '✔︎'),\n 'A': $version($d, 'A'),\n 'B': $version($d, 'B'),\n 'Position': string($person/@deltaxml:original-position)\n },\n if (position() eq last()) then \n map {'Field': '-', 'OK': '', 'A': '', 'B': '', 'Position': ''} \n else ()\n )"},{"kind":2,"language":"xpath","value":"/contacts/person//*[not(self::deltaxml:*) and empty(* except deltaxml:*)]! (., string-join(text()[1], '/'))"}] -------------------------------------------------------------------------------- /notebooks/demo/dataCompare/compare-result.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | Betty 5 | Alpha 6 |
7 | 8 | 9 | WR18 4GU 10 | B92 6DC 11 | 12 | 13 |
14 | Engineer 15 |
16 | 17 | Alan 18 | Alpha 19 |
20 | 21 | 22 | B92 6DC 23 | CR12 4QN 24 | 25 | 26 |
27 | Train Driver 28 |
29 |
-------------------------------------------------------------------------------- /src/cellStatusProvider.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { ExtensionData } from './extensionData'; 3 | 4 | export class CellStatusProvider implements vscode.NotebookCellStatusBarItemProvider { 5 | onDidChangeCellStatusBarItems?: vscode.Event | undefined; 6 | 7 | provideCellStatusBarItems(_cell: vscode.NotebookCell, _token: vscode.CancellationToken): vscode.ProviderResult { 8 | const items: vscode.NotebookCellStatusBarItem[] = []; 9 | const opLen = _cell.outputs.length; 10 | const op = opLen > 0? _cell.outputs[opLen - 1] : undefined; 11 | let fName: string | undefined; 12 | if (op && op.metadata) { 13 | fName = op.metadata['xpathContext']; 14 | const statusFname = fName? `Source: '${fName}'` : '(No evaluation context)' 15 | const item = new vscode.NotebookCellStatusBarItem(statusFname, vscode.NotebookCellStatusBarAlignment.Right); 16 | // TODO: add this command when available fix for: https://github.com/microsoft/vscode/issues/124529 17 | //item.tooltip = "Select new source"; 18 | //item.command = { title: "title", command: "xp-notebook.setSource", arguments: [_cell]}; 19 | 20 | items.push(item); 21 | 22 | const resultCount: number | undefined = op.metadata['resultCount']; 23 | const resultText = resultCount? `Items: ${resultCount}` : ''; 24 | const resultCountitem = new vscode.NotebookCellStatusBarItem(resultText, vscode.NotebookCellStatusBarAlignment.Right); 25 | items.push(resultCountitem); 26 | } 27 | 28 | return items; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /notebooks/gdpbycountry/gdpByCountry.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22,675,271 6 | 22,675,271 7 | 22,675,271 8 | 9 | 10 | 11 | 12 | 13 | 16,642,318 14 | 14,342,933 15 | 14,722,731 16 | 17 | 18 | 19 | 20 | 5,378,136 21 | 5,082,465 22 | 5,064,873 23 | 24 | 25 | 26 | 27 | 4,319,286 28 | 3,861,123 29 | 3,806,060 30 | 31 | 32 | 33 | 34 | 3,124,650 35 | 2,826,441 36 | 2,707,744 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/xbookSerializer.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | interface RawNotebookCell { 4 | language: string; 5 | value: string; 6 | kind: vscode.NotebookCellKind; 7 | } 8 | 9 | export class XBookSerializer implements vscode.NotebookSerializer { 10 | async deserializeNotebook( 11 | content: Uint8Array, 12 | _token: vscode.CancellationToken 13 | ): Promise { 14 | var contents = new TextDecoder().decode(content); 15 | if (contents.length === 0) { 16 | return new vscode.NotebookData([]); 17 | } 18 | 19 | let raw: RawNotebookCell[]; 20 | try { 21 | raw = JSON.parse(contents); 22 | } catch { 23 | vscode.window.showErrorMessage("Unable to parse 'xbook' JSON"); 24 | return new vscode.NotebookData([]); 25 | } 26 | 27 | if (!Array.isArray(raw)) { 28 | vscode.window.showErrorMessage("Error parsing 'xbook' JSON: expected array"); 29 | return new vscode.NotebookData([]); 30 | } else { 31 | const cells: vscode.NotebookCellData[] = [] 32 | for (let index = 0; index < raw.length; index++) { 33 | const cellData = raw[index]; 34 | if (cellData.kind !== undefined && cellData.value !== undefined && cellData.language !== undefined) { 35 | cells.push(new vscode.NotebookCellData(cellData.kind, cellData.value, cellData.language)); 36 | } else { 37 | vscode.window.showErrorMessage("Error parsing 'xbook' JSON: missing 'kind', 'value' or 'language' property"); 38 | return new vscode.NotebookData([]); 39 | } 40 | } 41 | return new vscode.NotebookData(cells); 42 | } 43 | } 44 | 45 | async serializeNotebook( 46 | data: vscode.NotebookData, 47 | _token: vscode.CancellationToken 48 | ): Promise { 49 | let contents: RawNotebookCell[] = []; 50 | 51 | for (const cell of data.cells) { 52 | contents.push({ 53 | kind: cell.kind, 54 | language: cell.languageId, 55 | value: cell.value 56 | }); 57 | } 58 | 59 | return new TextEncoder().encode(JSON.stringify(contents)); 60 | } 61 | } -------------------------------------------------------------------------------- /notebooks/gdpbycountry/gdpByCountry.xbook: -------------------------------------------------------------------------------- 1 | [{"kind":1,"language":"markdown","value":"## Visual Studio Code XPath Notebook Tutorial\n\n### Markdown Cell ###\n1. The text rendered here is in a **Markdown cell**\n2. To edit the styled output here as Markdown, double-click on this cell\n3. To exit editing mode, press *⌃Enter*\n### Code Cell ###\n1. The cell below this cell is a **Code cell** containing an XPath expression\n2. A Status Bar is shown at the bottom of each Code cell\n3. The Status Bar item *XPath* identifies the cell's programming language\n4. Clicking on the **XPath** Status Bar item would allow you to switch other language options for the cell\n5. The `[]` label left of the Status Bar shows the execution order of the cell\n6. Select the Code cell by clicking on it\n7. Press *⌃Enter* to execute the selected Code cell\n8. The 'Execution Order' label now shows: `[1]`\n9. On success, the Status Bar should show something like: `✔︎ 0.2s`\n### Output cell\n1. A new **Output cell**, below the Code cell, now shows the result: `\"Hello World\"`\n2. Use the `` button left of the cell to change the mimetype from `text/x-json` to `text/html`\n3. The Output cell now shows a 'table' with a single row and column\n"},{"kind":2,"language":"xpath","value":"'Hello ' || 'World'"},{"kind":1,"language":"markdown","value":"# Country/GDP Analysis\n\n## Visual Studio Code XPath Notebook Basics\n\n### Using an XML Source\n\n\n1. Open the `gdpByCountry.xml` file to make it the 'Context Item'"},{"kind":2,"language":"xpath","value":"/countries/country"},{"kind":1,"language":"markdown","value":"Using the `$_` variable to reference previous output. The result here is a `sequence` of `array` items. (XPath sequences, when represented in JSON, use the same `[]` notation in JSON as XPath arrays):"},{"kind":2,"language":"xpath","value":"array { 'Country', 'GBP $' }, \n$_! array {\n (@name, gdp-estimates/estimate[@org eq 'imf'])! string()\n}"},{"kind":1,"language":"markdown","value":"Assigning a result to a specific variable name:"},{"kind":2,"language":"xpath","value":"variable = total %\ncount(/countries/country)"},{"kind":1,"language":"markdown","value":"Using a named variable:"},{"kind":2,"language":"xpath","value":"'Total number of countries: ' || $total"}] -------------------------------------------------------------------------------- /src/jsonDefinitionProvider.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { ExtensionData } from './extensionData'; 3 | 4 | export class JsonDefinitionProvider implements vscode.DefinitionProvider { 5 | 6 | public async provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { 7 | 8 | 9 | return new Promise( async (resolve) => { 10 | 11 | let location: vscode.Location|undefined = undefined; 12 | const isCancelRequested = token.isCancellationRequested; 13 | const textLine = document.lineAt(position); 14 | const indicatorPos = textLine.text.indexOf('\u1680'); 15 | 16 | if (indicatorPos > 0 && 17 | textLine.text.charAt(indicatorPos - 1) === '"' && 18 | textLine.text.length - indicatorPos > 3 && 19 | textLine.text.charAt(indicatorPos + 1) === '/' 20 | ) { 21 | const xpathEndPos = textLine.text.indexOf(' ', indicatorPos); 22 | const xpath = textLine.text.substring(indicatorPos + 1, xpathEndPos); 23 | const xpathObj = {xpath: xpath, uri: ExtensionData.lastEditorUri}; 24 | const symbol = await vscode.commands.executeCommand( 25 | 'xslt-xpath.symbolFromXPath', 26 | xpathObj 27 | ); 28 | if (symbol) { 29 | const startPos = new vscode.Position(symbol.range.start.line, symbol.range.start.character); 30 | const endPos = new vscode.Position(symbol.range.end.line, symbol.range.end.character); 31 | const range = new vscode.Range(startPos, endPos); 32 | if (ExtensionData.lastEditorUri) { 33 | location = JsonDefinitionProvider.loocationFromRange(range, ExtensionData.lastEditorUri); 34 | } 35 | } 36 | 37 | } 38 | resolve(location); 39 | }); 40 | } 41 | 42 | private static loocationFromRange(range: vscode.Range, uriString: string) { 43 | return new vscode.Location(vscode.Uri.parse(uriString), range); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /notebooks/demo/demo.xbook: -------------------------------------------------------------------------------- 1 | [{"kind":1,"language":"markdown","value":"# Demonstration of XPath Notebooks in VS Code"},{"kind":2,"language":"xpath","value":"/countries/country[@name eq 'China']"},{"kind":2,"language":"xpath","value":""},{"kind":2,"language":"xpath","value":"\"Hello \" || \"World\""},{"kind":2,"language":"xpath","value":"map { \"country\": \"China\", \"gdp\": \"16,642,318\" },\nmap { \"country\": \"China\", \"gdp\": \"16,642,318\" }"},{"kind":2,"language":"xpath","value":"[/nothing]"},{"kind":2,"language":"xpath","value":"[ /*/new:country[@name eq 'China']\n]"},{"kind":2,"language":"xpath","value":"[ /*/new:country[@name eq 'China'],\n\"Hello \" || \"World\"\n]"},{"kind":2,"language":"xpath","value":"//new:*"},{"kind":2,"language":"xpath","value":"base-uri(), static-base-uri()"},{"kind":2,"language":"xpath","value":"for $country in /countries/country\nreturn map {$country/@name: string($country/gdp-estimates/estimate[@org eq 'imf'])}"},{"kind":1,"language":"markdown","value":"## XPath Notebook Tables\n\n### To output JSON that can be viewed as a simple table:\n\nFor each row in the table, create a map comprising a map-entry for each column:"},{"kind":2,"language":"xpath","value":"for $country in /countries/country\nreturn\n map:merge(\n (\n map:entry(\"Country\", string($country/@name)),\n map:entry(\"IMF GDP $\", string($country/gdp-estimates/estimate[@org eq 'imf'])),\n map:entry(\"UN GDP $\", string($country/gdp-estimates/estimate[@org eq 'un']))\n )\n )"},{"kind":1,"language":"markdown","value":"## GDP by country\nFor each country, create an **XPath map** with the country name and GDP estimates as map-entries."},{"kind":2,"language":"xpath","value":"for $country in /countries/country return\n (\n map {\n \"Country\": string($country/@name),\n \"IMF GDP $\": string($country/gdp-estimates/estimate[@org eq 'imf']),\n \"UN GDP $\": string($country/gdp-estimates/estimate[@org eq 'un'])\n }\n )"},{"kind":2,"language":"xpath","value":"map:merge(\nfor $country in /countries/country\nreturn map:entry(\n $country/@name,\n map:merge( \n for $est in $country/gdp-estimates/estimate\n return map {\n $est/@org: $est => replace(',', '') => xs:integer()\n }\n )\n )\n)\n"},{"kind":2,"language":"xpath","value":"map:merge(\n for $country in /countries/country\n return map:entry(\n $country/@name,\n $country/gdp-estimates/estimate!replace(.,',', '')!xs:integer(.)\n )\n)"}] -------------------------------------------------------------------------------- /src/extensionData.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as path from 'path'; 3 | import * as jsc from 'jsonc-parser' 4 | 5 | 6 | export class ExtensionData { 7 | static extensionPath: string = ''; 8 | static extensionURI: vscode.Uri | undefined; 9 | static lastEditorUri: string | undefined; 10 | 11 | static getSefPath() { 12 | const sefURI = vscode.Uri.joinPath(ExtensionData.extensionURI!, 'resources', 'xslt-sef', 'xpath-eval-to-json.sef.json'); 13 | return sefURI; 14 | } 15 | private static baseUri: string | undefined; 16 | private static staticBaseUri: string | undefined; 17 | private static nbScheme = 'vscode-notebook-cell'; 18 | 19 | 20 | 21 | static calcBaseUri(uri: vscode.Uri) { 22 | const path = uri.toString(); 23 | const pathEnd = path.lastIndexOf('/'); 24 | const result = path.substring(0, pathEnd); 25 | return result; 26 | } 27 | static setBaseUri(uri: vscode.Uri) { 28 | const result = this.calcBaseUri(uri); 29 | ExtensionData.baseUri = result; 30 | } 31 | 32 | static async getLastEditorText() { 33 | if (this.lastEditorUri) { 34 | return await vscode.workspace.fs.readFile(vscode.Uri.parse(this.lastEditorUri)); 35 | } 36 | } 37 | 38 | static isLastEditorTextValidJSON() { 39 | if (this.lastEditorUri) { 40 | const t = vscode.workspace.fs.readFile(vscode.Uri.parse(this.lastEditorUri)); 41 | } 42 | } 43 | 44 | static currentFormattedDate() { 45 | const dateObj = new Date(); 46 | 47 | const YYYY = dateObj.getFullYear(); 48 | // when calling getMonth, January is 0 49 | const MM = ExtensionData.padNumber(dateObj.getMonth() + 1); 50 | const DD = ExtensionData.padNumber(dateObj.getDate()); 51 | 52 | const hh = ExtensionData.padNumber(dateObj.getHours()); 53 | const mm = ExtensionData.padNumber(dateObj.getMinutes()); 54 | const ss = ExtensionData.padNumber(dateObj.getSeconds()); 55 | 56 | 57 | return `Date: ${YYYY}-${MM}-${DD}\xa0\xa0\xa0\xa0\xa0Time: ${hh}:${mm}:${ss}`; 58 | } 59 | 60 | static padNumber(number: number) { 61 | return number < 10 ? `0${number}` : number; 62 | } 63 | 64 | static initEditor(editor: vscode.TextEditor | undefined) { 65 | if (editor && editor.document.uri.scheme !== ExtensionData.nbScheme) { 66 | ExtensionData.registerEditor(editor); 67 | } else { 68 | const editors = vscode.window.visibleTextEditors; 69 | for (let index = 0; index < editors.length; index++) { 70 | const currentEditor = editors[index]; 71 | if (currentEditor.document.uri.scheme !== ExtensionData.nbScheme) { 72 | ExtensionData.registerEditor(editor); 73 | break; 74 | } 75 | } 76 | } 77 | } 78 | 79 | static registerEditor(editor: vscode.TextEditor | undefined) { 80 | if (editor) { 81 | if (editor.document.uri.scheme !== ExtensionData.nbScheme) { 82 | ExtensionData.lastEditorUri = editor.document.uri.toString(); 83 | ExtensionData.setBaseUri(editor.document.uri); 84 | } else { 85 | const fixedUri = `file:///${editor.document.uri.path}`; 86 | ExtensionData.staticBaseUri = fixedUri; 87 | } 88 | } 89 | } 90 | 91 | static getStaticBaseUri() { 92 | if (this.staticBaseUri) { 93 | return this.staticBaseUri; 94 | } 95 | const f = vscode.workspace.workspaceFolders; 96 | if (f && f.length > 0) { 97 | return this.calcBaseUri(f[0].uri); 98 | } else { 99 | return undefined; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xpath-notebook", 3 | "displayName": "XPath Notebook for Visual Studio Code", 4 | "description": "Notebook for XPath 3.1 - for analysing XML or JSON", 5 | "version": "0.2.0", 6 | "publisher": "deltaxml", 7 | "icon": "xpath-notebook.jpg", 8 | "bugs": { 9 | "url": "https://github.com/DeltaXML/vscode-xpath-notebook/issues" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/DeltaXML/vscode-xpath-notebook.git" 14 | }, 15 | "keywords": [ 16 | "xml", 17 | "json", 18 | "xpath", 19 | "notebook" 20 | ], 21 | "engines": { 22 | "vscode": "^1.70.2" 23 | }, 24 | "categories": [ 25 | "Programming Languages", 26 | "Notebooks", 27 | "Data Science" 28 | ], 29 | "activationEvents": [ 30 | "onNotebook:xbook", 31 | "workspaceContains:**/*.xbook", 32 | "workspaceContains:**\/*.ipynb", 33 | "onLanguage:xml", 34 | "onLanguage:xsl" 35 | ], 36 | "license": "MIT", 37 | "main": "./out/extension.js", 38 | "configurationDefaults": { 39 | "[xpath]": { 40 | "editor.semanticHighlighting.enabled": true 41 | }, 42 | "[json]": { 43 | "editor.semanticHighlighting.enabled": true 44 | }, 45 | "[javascript]": { 46 | "editor.semanticHighlighting.enabled": true 47 | } 48 | }, 49 | "contributes": { 50 | "menus": { 51 | "explorer/context": [ 52 | { 53 | "command": "xpath-notebook.newNotebook", 54 | "when": "resourceLangId == xslt" 55 | } 56 | ] 57 | }, 58 | "notebooks": [ 59 | { 60 | "id": "xbook", 61 | "type": "xbook", 62 | "displayName": "XBook", 63 | "selector": [ 64 | { 65 | "filenamePattern": "*.xbook" 66 | } 67 | ] 68 | } 69 | ], 70 | "commands": [ 71 | { 72 | "command": "xpath-notebook.newNotebook", 73 | "title": "New XPath Notebook" 74 | } 75 | ] 76 | }, 77 | "grammars": [ 78 | { 79 | "language": "xbook", 80 | "scopeName": "source.xbook", 81 | "path": "./syntaxes/JSON.tmLanguage.json" 82 | } 83 | ], 84 | "scripts": { 85 | "vscode:prepublish": "npm run compile && npm run compile-xsl", 86 | "compile": "tsc -p ./", 87 | "compile-xsl": "npx xslt3 -t -xsl:resources/xslt/xpath-eval-to-json.xsl -export:resources/xslt-sef/xpath-eval-to-json.sef.json -nogo", 88 | "lint": "tslint -p ./", 89 | "watch": "tsc -watch -p ./", 90 | "test": "jest" 91 | }, 92 | "extensionDependencies": [ 93 | "deltaxml.xslt-xpath" 94 | ], 95 | "devDependencies": { 96 | "@types/jest": "^24.9.1", 97 | "@types/node": "^10.17.17", 98 | "@types/vscode": "^1.66.0", 99 | "@types/vscode-notebook-renderer": "^1.60.0", 100 | "jest": "^26.6.3", 101 | "ts-jest": "^26.5.6", 102 | "tslint": "^5.20.1", 103 | "typescript": "^4.3.2", 104 | "xslt3": "^2.3.0" 105 | }, 106 | "dependencies": { 107 | "rimraf": "^3.0.2", 108 | "jsonc-parser": "^3.0.0", 109 | "saxon-js": "^2.3.0" 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { window } from 'vscode'; 3 | import { CellStatusProvider } from './cellStatusProvider'; 4 | import { ExtensionData } from './extensionData'; 5 | import { JsonDefinitionProvider } from './jsonDefinitionProvider'; 6 | import { JSONHoverProvider } from './jsonHoverProvider'; 7 | import { LinkProvider } from './linkProvider'; 8 | import { NotebookType, XBookController } from './xbookController'; 9 | import { XBookSerializer } from './xbookSerializer'; 10 | import { XpathResultTokenProvider } from './xpathResultTokenProvider'; 11 | import * as cp from 'child_process'; 12 | 13 | 14 | 15 | export function activate(context: vscode.ExtensionContext) { 16 | ExtensionData.extensionPath = context.extensionPath; 17 | ExtensionData.extensionURI = context.extensionUri; 18 | // prompt user to install Node.js - if not already installed. 19 | cp.exec('node -v', (error) => { 20 | if (error) { 21 | vscode.window.showWarningMessage("XPath Notebook requires a Node.js install from: https://nodejs.org/", "OK"); 22 | } 23 | }); 24 | 25 | const xbookController = new XBookController(NotebookType.xbook); 26 | // TODO: support ipynb when it supports saving language-info for XPath etc. 27 | const ipynbController = new XBookController(NotebookType.ipynb); 28 | // change package.json as follows: 29 | /* 30 | "activationEvents": [ 31 | "onNotebook:xbook", 32 | "workspaceContains:**\/*.xbook", 33 | "onNotebook:jupyter-notebook", 34 | "workspaceContains:**\/*.ipynb" 35 | ], 36 | */ 37 | 38 | async function setNotebookSource(cell: vscode.NotebookCell) { 39 | const options: vscode.OpenDialogOptions = { 40 | canSelectMany: false, 41 | openLabel: "Set as source" 42 | } 43 | const result = await window.showOpenDialog(options); 44 | if (result) { 45 | ExtensionData.lastEditorUri = result.toString(); 46 | xbookController._doExecution(cell); 47 | } 48 | } 49 | 50 | 51 | const newNotebook = async () => { 52 | const newNotebookContent = [ 53 | { 54 | "kind": 1, 55 | "languageId": "markdown", 56 | "value": `# XPath Notebook\n${ExtensionData.currentFormattedDate()}` 57 | }, 58 | { 59 | "kind": 2, 60 | "languageId": "xpath", 61 | "value": "" 62 | }, 63 | ]; 64 | const jsonNotebook = new vscode.NotebookData(newNotebookContent); 65 | const notebook = await vscode.workspace.openNotebookDocument('xbook', jsonNotebook); 66 | // TODO: uncomment once following is available 67 | //await vscode.window.showNotebookDocument(notebook); 68 | vscode.commands.executeCommand('vscode.open', notebook.uri); 69 | } 70 | 71 | ExtensionData.initEditor(vscode.window.activeTextEditor); 72 | 73 | context.subscriptions.push( 74 | vscode.languages.registerDocumentSemanticTokensProvider({ language: 'json' }, new XpathResultTokenProvider(), XpathResultTokenProvider.getLegend()), 75 | vscode.window.onDidChangeActiveTextEditor(editor => { 76 | ExtensionData.registerEditor(editor); 77 | }), 78 | vscode.languages.registerDocumentLinkProvider({ language: 'json' }, new LinkProvider()), 79 | vscode.notebooks.registerNotebookCellStatusBarItemProvider('xbook', new CellStatusProvider()), 80 | vscode.workspace.registerNotebookSerializer('xbook', new XBookSerializer()), 81 | vscode.commands.registerCommand('xpath-notebook.setSource', (...args) => setNotebookSource(args[0])), 82 | vscode.commands.registerCommand('xpath-notebook.newNotebook', newNotebook), 83 | xbookController, 84 | // TODO: see above 85 | ipynbController 86 | ); 87 | } 88 | 89 | export async function deactivate() { 90 | // await closeXBooks(); 91 | } 92 | -------------------------------------------------------------------------------- /src/linkProvider.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import { ExtensionData } from './extensionData'; 3 | import { LineType } from './xpathResultTokenProvider'; 4 | 5 | export class LinkProvider implements vscode.DocumentLinkProvider { 6 | 7 | provideDocumentLinks(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult { 8 | return this.extractLinksFromDocument(document); 9 | } 10 | 11 | /* 12 | { 13 | "allNodes": [ 14 | " /books[1]/book[1]/@author", 15 | " /books[1]/new:book[1]/@author" 16 | ], 17 | "node1": " /books[1]/book[1]/@author", 18 | "node2": " /books[1]/book[1]/@author" 19 | } 20 | 21 | */ 22 | extractLinksFromDocument(document: vscode.TextDocument): vscode.DocumentLink[] { 23 | const links: vscode.DocumentLink[] = []; 24 | 25 | const stack: LineType[] = []; 26 | const lines = document.getText().split(/\r?\n/); 27 | // TODO: ideally need to get uri from the output for the current active cell 28 | 29 | // compromise! 30 | const targetURI = ExtensionData.lastEditorUri? vscode.Uri.parse(ExtensionData.lastEditorUri) : undefined; 31 | 32 | if (!targetURI) return links; 33 | 34 | lines.forEach((line, lineNum) => { 35 | const lineType = stack.length > 0 ? stack[stack.length - 1] : LineType.None; 36 | const tLine = line.trim(); 37 | const padding = line.length - tLine.length; 38 | let char = tLine.charAt(0); 39 | const isLineStartString = char === '"'; 40 | if (isLineStartString) { 41 | char = tLine.charAt(tLine.length - 1); 42 | if (char !== '[' && char !== '{') { 43 | char = tLine.charAt(1); 44 | } 45 | } 46 | switch (char) { 47 | case '\u1680': 48 | if (tLine.charAt(2) === '/') { 49 | const propNameOffset = 0; 50 | this.pushLinks(tLine, propNameOffset, padding, links, lineNum, line, targetURI); 51 | } 52 | break; 53 | case '{': 54 | stack.push(LineType.Object); 55 | break; 56 | case '[': 57 | stack.push(LineType.Array); 58 | break; 59 | case '}': 60 | case ']': 61 | stack.pop(); 62 | break; 63 | default: 64 | if (lineType === LineType.Object) { 65 | let propNameOffset = tLine.indexOf('\u1680'); 66 | if (propNameOffset > -1) { 67 | this.pushLinks(tLine, propNameOffset - 1, padding, links, lineNum, line, targetURI); 68 | } 69 | } 70 | } 71 | }); 72 | return links; 73 | } 74 | 75 | private pushLinks(tLine: string, propNameOffset: number, padding: number, links: vscode.DocumentLink[], lineNum: number, _line: string, targetURI: vscode.Uri) { 76 | let spacePos = tLine.indexOf(' ', 3 + propNameOffset); 77 | const pathStart = padding + 2; 78 | const endPos = tLine.endsWith(',') ? tLine.length - 2 : tLine.length - 1; 79 | if (spacePos === -1) { 80 | spacePos = endPos; 81 | } 82 | if (targetURI) { 83 | const nodePath = tLine.substring(propNameOffset + 2, spacePos); 84 | const args = { xpath: nodePath, uri: targetURI.toString() } 85 | const argsString = encodeURIComponent(JSON.stringify(args)); 86 | const commandURI = vscode.Uri.parse(`command:xslt-xpath.selectXPathInDocument?${argsString}`); 87 | const startPathPos = new vscode.Position(lineNum, pathStart + propNameOffset + 1); 88 | const endPathPos = new vscode.Position(lineNum, pathStart + propNameOffset + 1 + (nodePath.length - 1)); 89 | const link = new vscode.DocumentLink(new vscode.Range(startPathPos, endPathPos), commandURI); 90 | link.tooltip = 'Goto XPath' 91 | links.push(link); 92 | } 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /src/htmlTables.ts: -------------------------------------------------------------------------------- 1 | import { Uri } from "vscode"; 2 | import { VSCodeEvent } from "vscode-notebook-renderer/events"; 3 | import { ExtensionData } from "./extensionData"; 4 | 5 | export class HtmlTables { 6 | 7 | private static ampRegex = /&/g; 8 | private static ltRegex = /${this.escape(obj.toString())}

` 22 | } 23 | } 24 | 25 | private static constructTableForArray(array: Array) { 26 | const tags: string[] = []; 27 | tags.push(''); 28 | array.forEach((item, index) => { 29 | if (index === 0 && typeof item === 'object' && !Array.isArray(item)) { 30 | tags.push(''); 31 | Object.keys(item).forEach(key => tags.push(``)); 32 | tags.push(''); 33 | } 34 | tags.push(''); 35 | if (Array.isArray(item)) { 36 | // array of arrays 37 | item.forEach((innerItem) => { 38 | tags.push(``); 39 | }) 40 | } else if (typeof item === 'object') { 41 | // array of objects 42 | Object.values(item).forEach(value => tags.push(``)); 43 | } else { 44 | tags.push(``); 45 | } 46 | tags.push(''); 47 | }); 48 | tags.push('
${this.escape(key)}
${this.escape(innerItem)}${this.escape(value)}${this.escape(item)}
'); 49 | return(tags.join('')); 50 | } 51 | 52 | 53 | private static constructTableForTopObject(obj: any) { 54 | const tags: string[] = []; 55 | tags.push(''); 56 | Object.entries(obj).forEach((item) => { 57 | const [key, value] = item; 58 | tags.push(''); 59 | tags.push(``); 60 | if (Array.isArray(value)) { 61 | value.forEach((innerItem) => { 62 | tags.push(``); 63 | }) 64 | } else { 65 | tags.push(``); 66 | } 67 | tags.push(''); 68 | }); 69 | tags.push('
${this.escape(key)}${this.escape(innerItem)}${this.escape(value)}
'); 70 | return(tags.join('')); 71 | } 72 | 73 | 74 | private static escape(obj: any) { 75 | if (typeof obj === 'string') { 76 | const str = obj; 77 | if (HtmlTables.targetURI && str.startsWith(this.xpathPrefix)) { 78 | let nodePath = str.substring(1); 79 | const args = { xpath: nodePath, uri: HtmlTables.targetURI.toString() } 80 | const argsString = encodeURIComponent(JSON.stringify(args)); 81 | const style = `text-decoration:none;`; 82 | return `${nodePath}` 83 | } else { 84 | return obj.replace(this.ampRegex, '&').replace(this.ltRegex, '<'); 85 | } 86 | } else { 87 | return JSON.stringify(obj).replace(this.ampRegex, '&').replace(this.ltRegex, '<'); 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /src/jsonHoverProvider.ts: -------------------------------------------------------------------------------- 1 | import { CancellationToken, Hover, HoverProvider, MarkdownString, Position, ProviderResult, TextDocument } from "vscode"; 2 | 3 | enum CharType { 4 | none, 5 | alphaNumeric, 6 | whitespace, 7 | openBracket, 8 | colon, 9 | other 10 | } 11 | 12 | export class JSONHoverProvider implements HoverProvider { 13 | 14 | provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult { 15 | const isCancelled = token.isCancellationRequested; 16 | const line = document.lineAt(position.line); 17 | let fnName = true; 18 | 19 | if (fnName) { 20 | const matchingData = true; 21 | if (matchingData) { 22 | return this.createHover("my signature", "description"); 23 | } 24 | } 25 | 26 | //return this.createHover('analyze\u2011string( input as xs:string?, pattern as xs:string, flags as xs:string ) as element(fn:analyze-string-result)', '*Something* is going to happen now'); 27 | } 28 | 29 | private createHover(signature: string, description: string) { 30 | return new Hover(new MarkdownString().appendCodeblock(signature, 'ts').appendMarkdown('\n' + description)); 31 | } 32 | 33 | private getFunctionName(line: string, char: number) { 34 | // track forwards to get end of potential function name 35 | let endChar = char; 36 | let findFirstEndSpace = true; 37 | let charType = CharType.none; 38 | 39 | while (endChar < line.length) { 40 | charType = this.classifyCharAtPos(line, endChar); 41 | if (charType !== CharType.alphaNumeric) { 42 | if (charType === CharType.colon) { 43 | // 44 | } else if (findFirstEndSpace) { 45 | if (charType === CharType.whitespace) { 46 | findFirstEndSpace = false; 47 | } else { 48 | break; 49 | } 50 | } else { 51 | if (charType !== CharType.whitespace) { 52 | break; 53 | } 54 | } 55 | } else { 56 | // is alphaNumeric 57 | if (!findFirstEndSpace) { 58 | break; 59 | } 60 | } 61 | endChar++; 62 | } 63 | 64 | if (charType !== CharType.openBracket) { 65 | return null; 66 | } 67 | 68 | let startChar = char -1; 69 | let findFirstStartColon = true; 70 | 71 | while (startChar > -1) { 72 | charType = this.classifyCharAtPos(line, startChar); 73 | if (charType !== CharType.alphaNumeric) { 74 | if (findFirstStartColon) { 75 | if (charType === CharType.colon) { 76 | findFirstStartColon = false; 77 | } else { 78 | break; 79 | } 80 | } else { 81 | break; 82 | } 83 | } 84 | startChar--; 85 | } 86 | 87 | startChar++; 88 | 89 | const result = line.substring(startChar, endChar); 90 | return result; 91 | 92 | } 93 | 94 | 95 | 96 | classifyCharAtPos(line: string, charPos: number) { 97 | const CHAR_CODE_A = 65; 98 | const CHAR_CODE_Z = 90; 99 | const CHAR_CODE_AS = 97; 100 | const CHAR_CODE_ZS = 122; 101 | const CHAR_CODE_0 = 48; 102 | const CHAR_CODE_9 = 57; 103 | const CHAR_CODE_DASH = 45; 104 | const CHAR_CODE_UNDERSCORE = 95; 105 | 106 | let code = line.charCodeAt(charPos); 107 | 108 | if (code === 9 || code === 10 || code === 12 || code === 32 ) { 109 | return CharType.whitespace; 110 | } else if (code === 35 || code === 40) { 111 | // the '#' char or '(' char 112 | return CharType.openBracket; 113 | } else if (code === 58) { 114 | return CharType.colon; 115 | } else { 116 | const isAlphaNumeric = ( 117 | (code >= CHAR_CODE_A && code <= CHAR_CODE_Z) || 118 | (code >= CHAR_CODE_AS && code <= CHAR_CODE_ZS) || 119 | (code >= CHAR_CODE_0 && code <= CHAR_CODE_9) || 120 | (code === CHAR_CODE_DASH || code === CHAR_CODE_UNDERSCORE ) 121 | ); 122 | const result = isAlphaNumeric? CharType.alphaNumeric : CharType.other; 123 | return result; 124 | } 125 | 126 | 127 | 128 | 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /src/xpathResultTokenProvider.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | export interface BaseToken { 4 | line: number; 5 | startCharacter: number; 6 | length: number; 7 | value: string; 8 | tokenType: number; 9 | } 10 | 11 | export enum LineType { 12 | Array, 13 | Object, 14 | None 15 | } 16 | 17 | enum TokenType { 18 | comment, 19 | nodeNameTest, 20 | xmlPunctuation, 21 | attributeNameTest 22 | } 23 | 24 | 25 | export class XpathResultTokenProvider implements vscode.DocumentSemanticTokensProvider { 26 | 27 | private static textmateTypes: string[] = []; 28 | private static tokenModifiers = new Map(); 29 | 30 | 31 | public static getTextmateTypeLegend(): string[] { 32 | 33 | // concat xsl legend to xpath legend 34 | if (XpathResultTokenProvider.textmateTypes.length === 0) { 35 | let keyCount: number = Object.keys(TokenType).length / 2; 36 | for (let i = 0; i < keyCount; i++) { 37 | XpathResultTokenProvider.textmateTypes.push(TokenType[i]); 38 | } 39 | } 40 | 41 | return XpathResultTokenProvider.textmateTypes; 42 | } 43 | 44 | public static getLegend() { 45 | const tokenTypesLegend = XpathResultTokenProvider.getTextmateTypeLegend(); 46 | 47 | const tokenModifiersLegend = [ 48 | 'declaration', 'documentation', 'member', 'static', 'abstract', 'deprecated', 49 | 'modification', 'async' 50 | ]; 51 | tokenModifiersLegend.forEach((tokenModifier, index) => XpathResultTokenProvider.tokenModifiers.set(tokenModifier, index)); 52 | 53 | return new vscode.SemanticTokensLegend(tokenTypesLegend, tokenModifiersLegend); 54 | }; 55 | 56 | async provideDocumentSemanticTokens(document: vscode.TextDocument): Promise { 57 | // console.log('provideDocumentSemanticTokens'); 58 | const builder = new vscode.SemanticTokensBuilder(); 59 | const stack: LineType[] = []; 60 | const lines = document.getText().split(/\r?\n/); 61 | const outLines: string[] = []; 62 | lines.forEach((line, lineNum) => { 63 | const lineType = stack.length > 0 ? stack[stack.length - 1] : LineType.None; 64 | const tLine = line.trimLeft(); 65 | const padding = line.length - tLine.length; 66 | let char = tLine.charAt(0); 67 | const isLineStartString = char === '"'; 68 | if (isLineStartString) { 69 | char = tLine.charAt(tLine.length - 1); 70 | if (char !== '[' && char !== '{') { 71 | char = tLine.charAt(1); 72 | } 73 | } 74 | switch (char) { 75 | case '\u1680': 76 | if (tLine.charAt(2) === '/') { 77 | const propNameOffset = 0; 78 | this.pushTokens(tLine, propNameOffset, padding, builder, lineNum, line); 79 | } 80 | break; 81 | case '{': 82 | stack.push(LineType.Object); 83 | break; 84 | case '[': 85 | stack.push(LineType.Array); 86 | break; 87 | case '}': 88 | case ']': 89 | stack.pop(); 90 | break; 91 | default: 92 | if (lineType === LineType.Object) { 93 | let propNameOffset = tLine.indexOf('\u1680'); 94 | if (propNameOffset > -1) { 95 | this.pushTokens(tLine, propNameOffset - 1, padding, builder, lineNum, line); 96 | } 97 | } 98 | } 99 | }); 100 | 101 | return builder.build(); 102 | } 103 | 104 | private pushTokens(tLine: string, propNameOffset: number, padding: number, builder: vscode.SemanticTokensBuilder, lineNum: number, line: string) { 105 | let spacePos = tLine.indexOf(' ', 3 + propNameOffset); 106 | const pathStart = padding + 2; 107 | builder.push(lineNum, padding + propNameOffset, 1, TokenType.xmlPunctuation, 0); 108 | builder.push(lineNum, padding + propNameOffset + 1, 1, TokenType.xmlPunctuation, 0); 109 | const endPos = tLine.endsWith(',') ? line.length - 2 : line.length - 1; 110 | if (spacePos === -1) { 111 | spacePos = endPos; 112 | } 113 | builder.push(lineNum, endPos, 1, TokenType.xmlPunctuation, 0); 114 | const path = tLine.substring(propNameOffset, spacePos); 115 | const pathParts = path.split('@'); 116 | let prevPartLen = 0; 117 | pathParts.forEach((part, index) => { 118 | if (index === 0) { 119 | builder.push(lineNum, pathStart + propNameOffset, part.length - 2, TokenType.nodeNameTest, 0); 120 | prevPartLen = part.length; 121 | } else { 122 | builder.push(lineNum, pathStart + propNameOffset + prevPartLen - 2, part.length + 1, TokenType.attributeNameTest, 0); 123 | } 124 | }); 125 | } 126 | } -------------------------------------------------------------------------------- /src/xbookController.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { HtmlTables } from './htmlTables'; 3 | import { NodeKernel } from './nodeKernel'; 4 | import { ExtensionData } from './extensionData'; 5 | import * as path from 'path'; 6 | 7 | export enum NotebookType { 8 | xbook = "xbook", 9 | ipynb = "jupyter-notebook" 10 | } 11 | 12 | 13 | export class XBookController { 14 | readonly controllerId: string = 'xbook-id'; 15 | readonly notebookType: NotebookType = NotebookType.xbook; 16 | readonly label = 'XPath Notebook'; 17 | readonly supportedLanguages = ['xpath', 'javascript']; 18 | private readonly nodeKernel: NodeKernel; 19 | 20 | private readonly _controller: vscode.NotebookController; 21 | private _executionOrder = 0; 22 | 23 | constructor(type: NotebookType) { 24 | this._controller = vscode.notebooks.createNotebookController( 25 | this.controllerId = 'xpath:' + type, 26 | this.notebookType = type, 27 | this.label 28 | ); 29 | 30 | this._controller.supportedLanguages = this.supportedLanguages; 31 | this._controller.supportsExecutionOrder = true; 32 | this._controller.executeHandler = this._execute.bind(this); 33 | this._controller.interruptHandler = this._interrupt.bind(this); 34 | 35 | this.nodeKernel = new NodeKernel(); 36 | } 37 | 38 | private async _execute( 39 | cells: vscode.NotebookCell[], 40 | _notebook: vscode.NotebookDocument, 41 | _controller: vscode.NotebookController 42 | ): Promise { 43 | for (let cell of cells) { 44 | await this._doExecution(cell); 45 | } 46 | vscode.commands.executeCommand('xslt-xpath.setVariableNames', this.nodeKernel.getVariableNames()); 47 | } 48 | 49 | private _interrupt() { 50 | this.nodeKernel.stop(); 51 | } 52 | 53 | public async _doExecution(cell: vscode.NotebookCell): Promise { 54 | const execution = this._controller.createNotebookCellExecution(cell); 55 | execution.executionOrder = ++this._executionOrder; 56 | execution.start(Date.now()); // Keep track of elapsed time to execute cell. 57 | 58 | await this.nodeKernel.start(); 59 | let isSuccess = true; 60 | let result = ''; 61 | try { 62 | result = await this.nodeKernel.eval(cell); 63 | const { prolog, main } = XBookController.separatePrologFromXPath(cell.document.getText()); 64 | if (prolog && main) { 65 | const parts = prolog.split('='); 66 | if (parts.length === 2) { 67 | if (parts[0].trim() === 'variable') 68 | try { 69 | vscode.commands.executeCommand('xslt-xpath.setExtensionXPathVariable', parts[1].trim(), main); 70 | } catch { 71 | // do nothing if command fails - poss due to dated XSLT/XPath extension 72 | } 73 | } 74 | } 75 | } catch (error: any) { 76 | result = error; 77 | isSuccess = false; 78 | } 79 | 80 | let contextString: string | undefined; 81 | if (ExtensionData.lastEditorUri) { 82 | const fsPath = vscode.Uri.parse(ExtensionData.lastEditorUri).fsPath; 83 | contextString = path.basename(fsPath); 84 | } 85 | 86 | const metadata = { 87 | 'xpathContext': contextString, 88 | 'resultCount': 0, 89 | 'xpathContextUri': ExtensionData.lastEditorUri 90 | }; 91 | 92 | if (isSuccess) { 93 | const resultObj = JSON.parse(result); 94 | //const jsonTextResult = JSON.stringify(resultObj, null, 4); 95 | const htmlString = HtmlTables.constructTableForObject(resultObj); 96 | const itemCount = Array.isArray(resultObj)? resultObj.length : 1; 97 | metadata.resultCount = itemCount; 98 | 99 | execution.replaceOutput([ 100 | new vscode.NotebookCellOutput([ 101 | // vscode.NotebookCellOutputItem.text(jsonTextResult, 'text/x-javascript'), 102 | vscode.NotebookCellOutputItem.text(htmlString, 'text/html'), 103 | vscode.NotebookCellOutputItem.json(resultObj, 'application/json'), 104 | ], metadata) 105 | ]); 106 | } else { 107 | execution.replaceOutput([ 108 | new vscode.NotebookCellOutput([ 109 | vscode.NotebookCellOutputItem.text(result) 110 | ], metadata) 111 | ]); 112 | } 113 | execution.end(isSuccess, Date.now()); 114 | } 115 | 116 | private static separatePrologFromXPath(text: string) { 117 | const percentPos = text.indexOf('%'); 118 | let prolog: string|undefined; 119 | let main: string|undefined; 120 | if (percentPos !== -1) { 121 | const singlePos = text.indexOf('\''); 122 | const doublePos = text.indexOf('\"'); 123 | let minpos = percentPos; 124 | if (singlePos !== -1 && doublePos !== -1) { 125 | minpos = Math.min(percentPos, singlePos, doublePos); 126 | } else if (singlePos !== -1 ) { 127 | minpos = Math.min(percentPos, singlePos); 128 | } else if (doublePos !== -1 ) { 129 | minpos = Math.min(percentPos, doublePos); 130 | } 131 | if (percentPos === minpos) { 132 | prolog = text.substring(0, percentPos); 133 | main = text.substring(percentPos + 1); 134 | } 135 | } 136 | return { prolog, main} 137 | } 138 | 139 | public dispose() { 140 | this.nodeKernel.stop(); 141 | } 142 | } -------------------------------------------------------------------------------- /notebooks/introduction/xpath-notebook.xbook: -------------------------------------------------------------------------------- 1 | [{"kind":1,"language":"markdown","value":"# XPath Notebook Introduction\n\nThis XPath Notebook describes [DeltaXML's XPath Notebook extension](https://marketplace.visualstudio.com/items?itemName=deltaxml.xpath-notebook) for Visual Studio Code. \n\nHere we cover the fundamentals of using XPath 3.1 in a [Visual Studio Code Notebook](https://code.visualstudio.com/blogs/2021/11/08/custom-notebooks). \n\n## What can XPath Notebooks be used for? \n\nAn XPath Notebook may be used for a range of purposes, including:\n\n- Data Analysis (of JSON or XML)\n- Experimentation with XPath\n- Tutorials on specific XML/JSON formats or XPath itself\n- Learning XPath\n\n## Evaluation Context\n\nEach XPath code cell executed in a notebook has an **Evaluation Context**:\n\n1. Any XPath expression in a Notebook can reference a *context item*. \n - The *context item* is the parsed form of the last (valid) XML or JSON file opened in Visual Studio Code \n2. The `$_` variable in the evaluation context holds the result of the last executed cell\n3. XPath Notebook variables like `$myvar` are used to reference results from previously executed cells\n - An 'XPath Prolog' like `variable=myvar%` for a Code cell stores the XPath result in the variable `myvar`\n6. The **Static Base URI** is set to the Notebook file URI\n7. The dynamic **Base URI** is set to the context file URI - if this is an XML file\n8. XML namespaces from the root element of an XML context file are added to the evaluation context\n9. Common prefix/namespace-uri bindings like `array`, `map` and `xs` are always added to the XPath evaluation context\n"},{"kind":1,"language":"markdown","value":"## Notebook Cells\nEach XPath Notebook comprises a set of **Cells**:"},{"kind":1,"language":"markdown","value":"### Markdown Cell ###\n1. The text rendered here is in a **Markdown cell**\n2. To edit the styled output here as Markdown, double-click on this cell\n3. To exit editing mode, press *⌃Enter*\n4. Headings in Markdown cells affect the **Outline view** tree shown in the **Explorer** Side Bar"},{"kind":1,"language":"markdown","value":"### Code Cell ###\n1. The first **Code cell** in this Notebook contains the XPath expression `'Hello '` || `'World'`\n2. A **Status Bar** is shown at the bottom of each Code cell\n3. The Status Bar item *XPath* identifies the cell's programming language\n4. Clicking on the **XPath** Status Bar item would allow you to switch other language options for the cell\n5. The `[]` label left of the Status Bar shows the execution order of the cell\n6. Select the first Code cell by clicking on it\n7. Press *⌃Enter* to execute the selected Code cell\n8. The 'Execution Order' label now shows: `[1]`\n\n#### Code Cell Status Bar\n1. On success, the Status Bar should show something like: `✔︎ 0.2s`\n2. The name of the *context item* file is shown in the Status Bar\n3. The Status bar shows the number of array or sequence items in a result"},{"kind":1,"language":"markdown","value":"### Output Cell\n1. A new **Output cell**, below the Code cell, now shows the result: `\"Hello World\"`\n2. The default Output cell mimetype is `text/x-json`\n2. Use the `` button left of the cell to change the mimetype to `text/html`\n3. The Output cell now shows a 'table' with a single row and column"},{"kind":2,"language":"xpath","value":"'Hello ' || 'World'"},{"kind":1,"language":"markdown","value":"## Cell Output Types\nNotebook cells can support a number of output types, these are identified by a *mimetype*. The XPath Notebook currently supports `text/x-json` and `text/html` output types.\n\nYou can switch the mimetype of an Output cell by clicking on the `` button immediately to the left of the cell"},{"kind":1,"language":"markdown","value":"### JSON Output\n1. The default Cell output type is JSON - using the mimetype `text/x-json`\n2. XPath sequences and arrays are represented as JSON arrays\n3. XPath maps are represented as JSON objects with properties corresponding to map keys\n4. XPath nodes are represented as XPath strings with special highlighting\n5. Support for XPath types like `QName` that don't have a JSON equivalent is a **Work in Progress**"},{"kind":1,"language":"markdown","value":"#### Representing XPath Sequences and Arrays\n1. XPath sequences and arrays are both represented as JSON arrays\n2. When executed, the Code cell below results in an XPath sequence. Each sequence item is itself an array\n3. With the result output as JSON, the result is seen as an array of arrays"},{"kind":2,"language":"xpath","value":"['London', 25], \n['New York', 32]"},{"kind":1,"language":"markdown","value":"#### Representing XPath Maps\n1. XPath Maps are represented as JSON objects\n2. Map keys correspond to JSON object property names\n3. When JSON is parsed by XPath, JSON objects are processed as XPath maps\n3. If the Code cell below is executed, the result is a sequence of maps\n4. (In the JSON representation this is shown as an array of objects)"},{"kind":2,"language":"xpath","value":"map { 'City': 'London', 'Temperature': 22 },\nmap { 'City': 'New York', 'Temperature': 32 }"},{"kind":1,"language":"markdown","value":"#### Representing XML Nodes\n1. When XPath is executed the result may be an XML Node such as an Element or Arribute\n2. The result is represented in JSON as a string holding the XPath location of the node. \n3. Each XPath location string is prefixed with the Unicode Character 'OGHAM SPACE MARK' `U+1680`\n4. XPath location strings are identifiable by special syntax highlighting\n5. `CMD + click` on an XPath location to highlight the node in the XML source (currently the source file URI is assumed to be that of the context item)\n6. Executing the two XPath cells below (repeat ⇧Enter to execute and move to next cell) results in a sequence of XML Attribute nodes"},{"kind":2,"language":"xpath","value":"variable = data-uri % resolve-uri('../gdpbycountry/gdpByCountry.xml', static-base-uri())"},{"kind":1,"language":"markdown","value":"*Note: XPath below uses the `$data-uri` context variable declared in the XPath Prolog above*"},{"kind":2,"language":"xpath","value":"doc($data-uri)/countries/country[@region eq 'Europe']/@name"},{"kind":1,"language":"markdown","value":"#### Representing Primitive Types\n\n1. The most basic XPath types are supported with their JSON equivalent\n2. The string equivalent of XPath types such as `QName` are used\n3. An XPath empty-sequence is currently represented as`[]`"},{"kind":1,"language":"markdown","value":"### HTML Data Table\n1. This output type uses the mimetype `text/html`\n2. The Output cell is rendered as an HTML table\n3. Each table row corresponds to a JSON array item that may be an object or another nested array\n4. Each table corresponds to either a property of an object or a nested-array item\n5. Change the Output cells in this notebook by clicking on the `` button to the `text/html` mimetype to see the table representation\n\n*Note: This output type is light-weight and quite primitve in implementation. For large data-sets or rich table rendering it is recommended you install and use third-party Notebook renderer extensions (like [RandomFractals Data Table](https://marketplace.visualstudio.com/items?itemName=RandomFractalsInc.vscode-data-table)) for the `text/x-json` output type.*"}] -------------------------------------------------------------------------------- /src/nodeKernel.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as cp from 'child_process'; 3 | import * as fs from 'fs'; 4 | import * as os from 'os'; 5 | const rmdir = require('rimraf'); 6 | 7 | 8 | import * as PATH from 'path'; 9 | import { ExtensionData } from './extensionData'; 10 | 11 | export class NodeKernel { 12 | 13 | private nodeRuntime: cp.ChildProcess | undefined; 14 | private outputBuffer = ''; // collect output here 15 | private hasRuntimeError = false; 16 | private outputKeys = ''; 17 | private tmpDirectory?: string; 18 | 19 | public async start() { 20 | if (!this.nodeRuntime) { 21 | 22 | this.nodeRuntime = cp.spawn('node', [ 23 | `-e`, `require('repl').start({ prompt: '', ignoreUndefined: true })` 24 | ]); 25 | 26 | this.runSaxonLoader(); 27 | if (this.nodeRuntime.stdout) { 28 | this.nodeRuntime.stdout.on('data', (data: Buffer) => { 29 | const dataStr = data.toString(); 30 | if (dataStr.startsWith('Uncaught')) { 31 | this.hasRuntimeError = true; 32 | this.outputBuffer += dataStr.substring(15); 33 | } else if (dataStr.includes('\nUncaught')) { 34 | this.hasRuntimeError = true; 35 | this.outputBuffer += dataStr; 36 | } else if (dataStr.includes('#keys#')) { 37 | // remove prefix and surrounding ' chars 38 | this.outputKeys = dataStr.substring(7, dataStr.length - 2); 39 | } else { 40 | this.outputBuffer += dataStr; 41 | } 42 | }); 43 | } 44 | 45 | if (this.nodeRuntime.stderr) { 46 | this.nodeRuntime.stderr.on('error', (data: Buffer) => { 47 | this.hasRuntimeError = true; 48 | this.outputBuffer += data.toString(); 49 | console.log(`stderr: ${data}`); 50 | }); 51 | } 52 | } 53 | } 54 | 55 | public async eval(cell: vscode.NotebookCell): Promise { 56 | 57 | const cellPath = cell.document.languageId === 'xpath' ? this.dumpCell(cell) : this.dumpCell(cell); // TODO: dumpJSCell 58 | if (cellPath && this.nodeRuntime && this.nodeRuntime.stdin) { 59 | this.outputBuffer = ''; 60 | this.outputKeys = ''; 61 | this.hasRuntimeError = false; 62 | 63 | this.nodeRuntime.stdin.write(`.load ${cellPath}\n`); 64 | while (this.outputBuffer === '') { 65 | await this.sleep(100); 66 | } 67 | if (!this.hasRuntimeError) { 68 | this.nodeRuntime.stdin.write(`globalVariables.getKeysJSON()\n`); 69 | while (this.outputKeys === '') { 70 | await this.sleep(100); 71 | } 72 | } 73 | 74 | if (this.hasRuntimeError) { 75 | return Promise.reject(this.outputBuffer); 76 | } else { 77 | return Promise.resolve(this.outputBuffer); 78 | } 79 | } 80 | throw new Error('Evaluation failed'); 81 | } 82 | 83 | private sleep(time: number) { 84 | return new Promise(res => setTimeout(res, time)); 85 | } 86 | 87 | private dumpCell(cell: vscode.NotebookCell): string | undefined { 88 | try { 89 | 90 | const cellUri = cell.document.uri; 91 | let cellText = cell.document.getText(); 92 | cellText = cellText.replaceAll('\\', '\\\\'); 93 | cellText = cellText.replaceAll('\`', '\\`'); 94 | if (cellUri.scheme === 'vscode-notebook-cell') { 95 | // set context 96 | let contextScript = ''; 97 | contextScript = ` 98 | globalVariables.staticBaseURI = '${ExtensionData.getStaticBaseUri()}'; 99 | `; 100 | 101 | let data = contextScript; 102 | data += "try {\n" 103 | //data += "prevResult = SaxonJS.XPath.evaluate(\`" + cellText + "\`, context, options);\n"; 104 | data += ` 105 | let resultTransform = SaxonJS.transform({ 106 | stylesheetLocation: "${ExtensionData.getSefPath()}", 107 | initialTemplate: "main", 108 | stylesheetParams: { 109 | "sourceURI": "${ExtensionData.lastEditorUri}", 110 | "expression": \`${cellText}\`, 111 | "this": globalVariables 112 | } 113 | }); 114 | prevResult = '' + resultTransform.principalResult; 115 | ` 116 | data += ` 117 | console.log(prevResult); 118 | ` 119 | data += `} catch(error) { 120 | throw new Error(error.toString()); 121 | } `; 122 | const cellPath = `${this.tmpDirectory}/nodebook_cell_${cellUri.fragment}.js`; 123 | fs.writeFileSync(cellPath, data); 124 | return cellPath; 125 | } 126 | } catch (e) { 127 | } 128 | return undefined; 129 | } 130 | 131 | public async runSaxonLoader(): Promise { 132 | 133 | const saxonLoaderPath = this.dumpSaxonLoader(); 134 | if (saxonLoaderPath && this.nodeRuntime && this.nodeRuntime.stdin) { 135 | 136 | this.outputBuffer = ''; 137 | this.nodeRuntime.stdin.write(`.load ${saxonLoaderPath}\n`); 138 | 139 | //await new Promise(res => setTimeout(res, 500)); // wait a bit to collect all output that is associated with this eval 140 | // silent: 141 | this.outputBuffer = ''; 142 | return Promise.resolve(this.outputBuffer); 143 | } 144 | throw new Error('Evaluation failed'); 145 | } 146 | 147 | public getVariableNames() { 148 | return this.outputKeys === ''? [] : JSON.parse(this.outputKeys); 149 | } 150 | 151 | /** 152 | * Store cell in temporary file and return its path or undefined if uri does not denote a cell. 153 | */ 154 | private dumpSaxonLoader(): string | undefined { 155 | 156 | try { 157 | if (!this.tmpDirectory) { 158 | this.tmpDirectory = fs.mkdtempSync(PATH.join(os.tmpdir(), 'xpath-notebook-')); 159 | } 160 | const saxonLoaderPath = `${this.tmpDirectory}/saxonLoader.js`; 161 | const escapedSpacePath = ExtensionData.extensionPath; 162 | const joinedPath = PATH.join(escapedSpacePath, "node_modules", "saxon-js"); 163 | const escapedSlashPath = '"' + joinedPath.replace(/(\\)/g, '\\$1') + '"'; 164 | const arr = [1,2,3]; 165 | const tst = arr.indexOf(1); 166 | 167 | let script = ` 168 | const SaxonJS = require(${escapedSlashPath}); 169 | let prevResult = []; 170 | class GlobalVariables { 171 | staticBaseURI = ''; 172 | variables = {}; 173 | keys = []; 174 | setVariable = (name, value) => { 175 | if (this.keys.indexOf(name) === -1) { 176 | this.keys.push(name); 177 | } 178 | this.variables[name] = value; 179 | } 180 | getKeys = () => { 181 | return this.keys; 182 | } 183 | getKeysJSON = () => { 184 | return '#keys#' + JSON.stringify(this.keys); 185 | } 186 | getVariables = () => { 187 | return this.variables; 188 | } 189 | getVariable = (name) => { 190 | return this.variables[name]; 191 | } 192 | } 193 | const globalVariables = new GlobalVariables(); 194 | `; 195 | fs.writeFileSync(saxonLoaderPath, script); 196 | return saxonLoaderPath; 197 | } catch (e) { 198 | } 199 | return undefined; 200 | } 201 | 202 | public async restart() { 203 | this.stop(); 204 | await this.start(); 205 | } 206 | 207 | public stop() { 208 | 209 | if (this.nodeRuntime) { 210 | this.nodeRuntime.kill(); 211 | this.nodeRuntime = undefined; 212 | } 213 | 214 | if (this.tmpDirectory) { 215 | const t = this.tmpDirectory; 216 | this.tmpDirectory = undefined; 217 | rmdir(t, { glob: false }, (err: Error | undefined) => { 218 | if (err) { 219 | console.log(err); 220 | } 221 | }); 222 | } 223 | } 224 | 225 | 226 | 227 | } -------------------------------------------------------------------------------- /resources/xslt/test/test-eval.xsl: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 101 | 102 | 103 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # XPath Notebook for Visual Studio Code 4 | 5 | **XPath Notebook** adds XPath 3.1's extensive JSON and XML analysis features to [Visual Studio Code's Notebooks](https://code.visualstudio.com/blogs/2021/11/08/custom-notebooks). 6 | 7 | Notebooks can be used for data-analysis, code experimentation, tutorials or learning. 8 | 9 | 10 | ![XPath Notebook screenshot](xpath-notebook-small.png) 11 | # DeltaXignia's XPath Notebook Features 12 | 13 | | Feature | Details | 14 | | ------- | ------- | 15 | | **XPath 3.1 Compatible** | See W3C specifications for [XPath 3.1](https://www.w3.org/TR/xpath-31/#id-introduction) 16 | | **XPath Processing** | Requires [Node.js](https://nodejs.org/en/) to be installed. Uses Saxonica's [Saxon-JS Processor](https://www.saxonica.com/saxon-js/index.xml) 17 | | **JSON or XML sources** | The context for XPath evaluation can be JSON or XML files 18 | | **Syntax Highlighting** | Fast and precise - using [Semantic Highlighting](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide) exclusively 19 | | **Code Formatting** | For multi-line XPath expressions, 'as-you-type' or 'on-save' 20 | | **Code Diagnostics** | For XPath Syntax, variable/param references, functions, namespace-prefixes etc. 21 | | **Auto-Completion** | For XPath node-names, functions, variables, function-parameters etc. 22 | | **Color Theme Support** | Tested with most popular color themes ([Semantic Highlighting]() must be enabled in settings) 23 | | **Evaluation Context** | Sets context item, namespace context, context variables, last result variable 24 | | **Code Folding** | The indentation of XPath expressions is used to determine fold regions 25 | | **Notebook Context Variables** | An **XPath Prologue** (e.g. ` variable = countries %` ) assigns the cell result to a notebook variable 26 | | **Last Result Variable** | Use `$_` to reference the last evaluated notebook cell result 27 | | **Bracket Matching** | For `()`, `{}`, and `[]` 28 | | **Hover assistance** | Shows tooltips. Providing signatures and descriptions for all built-in XSLT and XPath 29 | | **JSON output** | View Cell output with the JSON syntax (suitable for 3rd-party renderers) - mime-type: `text/x-json` 30 | | **Table output** | View Cell output as a simple table - mime-type: `text/html` 31 | | **XML Node navigation** | Navigates to and highlights XML result nodes in the source document 32 | ||| 33 | 34 | 35 | # Introduction 36 | 37 | DeltaXignia's *XPath Notebook* extension adds comprehensive **XPath 3.1** support to Visual Studio Code's built-in notebooks. Visual Studio Code notebooks provide similar features to other popular notebook interfaces like the [Juypter Notebook](https://jupyterlab.readthedocs.io/en/latest/user/notebook.html#notebook). 38 | 39 | A notebook comprises a set of notebooks cells. These cells can either be **Markdown cells** for narrative content or **Code cells** for a specific programming language. 40 | 41 | When a Code cell is executed, the result is rendered in an **Output cell** immediately below the current Code cell. The currently active **NotebookController** (also known as a **Kernel**) determines the output types that can be shown in the Output cell. Each output type will have a corresponding **NotebookRenderer** that is responsible for formatting the output type. For example, the result may be shown as JSON text, as an interactive table or an interactive graphical plot. 42 | 43 | # Getting Started 44 | 45 | ## STEP 1: Setup the XPath Processor 46 | 47 | To evaluate XPath expressions, the XPath Notebook requires **Node.js** to be installed. The Node.js installer is available for download from: 48 | 49 | https://nodejs.org/en/. 50 | 51 | ## STEP 2: Create and save a new XPath Notebook 52 | 53 | Open the Visual Studio Code command palette (**⇧⌘P**), and run the `New XPath Notebook` command. An untitled notebook with a markdown cell and a code cell will be shown, initially the file is untitled with a `.xbook` file extension. 54 | 55 | Save the Notebook file in the usual way (*⌘S*), keeping the `.xbook` extension. *Note that XPath Notebook output cell values are not saved when the file is saved.* 56 | 57 | ![empty notebook](empty-notebook.png) 58 | 59 | 60 | ## STEP 3: Setup the XPath Source 61 | 62 | To set the evaluation context file for a notebook just open an XML or JSON file in Visual Studio Code. 63 | 64 | The context-item is the result of evaluating either [`doc($uri)`](https://www.w3.org/TR/xpath-functions-31/#func-doc) or 65 | [`json-doc($uri)`](https://www.w3.org/TR/xpath-functions-31/#func-json-doc) respectively on the last opened file (excluding notebook files). Here is a summary of the evaluation context: 66 | 67 | | Definition | Details | 68 | | ------- | ------- | 69 | | **Context Item** | [`doc($uri)`](https://www.w3.org/TR/xpath-functions-31/#func-doc) or [`json-doc($uri)`](https://www.w3.org/TR/xpath-functions-31/#func-json-doc) evaluated with last editor URI arg 70 | | **Statically known namespaces** | for prefixes: `array`, `map`, `math`, `xs`, `xsl`| 71 | | **Dynamically known namespaces** | from root element of last opened file - if it was XML | 72 | | **Default element namespace** | any default namespace on root element of last opened XML file | 73 | | **In-scope variables** | `$_` for last cell output
variables declared in prolog of executed cells 74 | | **Static Base URI** | the URI of the current XPath Notebook file 75 | | **Base URI** | the URI of the last opened file - if it was XML 76 | 77 | --- 78 | ## STEP 4: Add and execute Notebook cells 79 | 80 | Press the '`+ Code`' or '`+ Markdown`' buttons to add Code or Markdown cells. To execute a cell, press `Ctrl-ENTER` on the keyboard or click on the 'execute' button alongside the cell. When a Code cell is executed the result is shown in the Output cell immediately below the current cell. 81 | 82 | For XPath Notebooks the default Output Cell type is JSON text. This allows XPath maps, arrays and sequences to be represented in an intuitive way. 83 | 84 | ## Step 5: Save the XPath Notebook when done 85 | 86 | Use the `CMD-S` keyboard shortcut to save an XPath Notebook so it can be used again. Currently, the Output cell details are not saved. 87 | 88 | # General Usage 89 | 90 | ## Result node navigation 91 | 92 | If a result item is an XML node the XPath for the node is shown with special syntax highlighting. Result nodes can be navigated easily: first press and hold the `CMD` button and then click on the XPath in the output cell. The corresponding source XML document will be shown alongside the XPath Notebook, with the corresponding node highlighted. 93 | 94 | > To view the string values of XML nodes in the output cell 95 | > you should convert them to a string, for example, using the `string()` function, for example: `/books/book/@author! string()` 96 | 97 | ![empty notebook](json-output.png) 98 | 99 | *Sample JSON output cell showing special syntax highlighting for XML nodes* 100 | 101 | ## Add NoteBook Context Variables 102 | 103 | XPath expressions in code cells can reference the results of other code cells. The `$_` variable is always set to the result of the previously executed cell. If you want to assign the result of a cell to a specific XPath variable, use a special *XPath Prolog** as the first line. 104 | 105 | An XPath Prolog is separated from the XPath expression with the `%` character as this is not a valid XPath operator. The syntax for the prolog is: 106 | ```xml 107 | variable = % 108 | ``` 109 | In the above, `` is the name of the variable to which we assign the evaluation result of the following XPath expression. 110 | 111 | > *Note: The intension is to use the XPath Prolog for other features later.* 112 | 113 | In the example below, the result of the `$cities` variable declared in cell `[4]` is used when cell `[5]` is executed: 114 | 115 | ![cell variables](cell-variables.png) 116 | 117 | ## Problem Reporting 118 | 119 | XPath expressions in Code cells are checked against basic syntax rules. Also, variable names and namespace prefixes are checked using the evaluation context (described above). References to Notebook context variables are marked as invalid until the Code cell with the corresponding variable assignment is executed. 120 | 121 | ## Auto-completion 122 | 123 | Auto-completion is available when editing inside Code cells. Auto-completion is triggered for XPath functions and variable names. The variable names list will include Notebook context variables only once the corresponding cells have been evaluated. 124 | 125 | ## Choosing Cell Output Type 126 | 127 | Currently XPath Notebooks supports two output types: 128 | 129 | | Mime-type | Details | 130 | | ------- | ------- | 131 | | **text/html** | suitable for small data-sets (< 1MB) shows results in tabular form 132 | | **text/x-json** | for JSON text view or advanced rendering from 3rd party VS Code extensions such as [RandomFractal's VSCode Data Table](https://github.com/RandomFractals/vscode-data-table) 133 | 134 | > **Note**: RandomFractals Data Table renderer supports large data sets and provides column sort and data-type formatting. 135 | 136 | To select an alternative output type, press the ![consolidated-button](consolidated-button.png) (consolidated) output button or the ![button](button.png) (normal) output button shown to the left of the output cell. Then select the `text/html` mime-type. *(See the note below to see how to control what button is shown)*. 137 | 138 | ![html table](html-output-cell.png) 139 | 140 | > *Note: A Notebook Layout setting (`@tag:notebookLayout consolidated output button`) control whether you see a 'consolidated' or 'normal' button alongside the Notbook output cell. For this extension, it's more convenient to disable the 'consolidated' button.* 141 | 142 | # Implementation Detail 143 | 144 | ## Evaluation 145 | 146 | The XPath Notebook uses the [Node.js REPL](https://nodejs.org/api/repl.html#repl_the_node_js_repl) to execute XPath cells. The [Saxon-JS](https://www.npmjs.com/package/saxon-js) NPM module from [Saxonica](https://www.saxonica.com/saxon-js/documentation/index.html) is pre-installed with the extension. 147 | 148 | To evaluate an XPath expression the `SaxonJS.transform` function invoked via the Node.js REPL. The XSLT used in the transorm is a compiled *SEF* file, the XPath expression and evaluation context are passed as XSLT parameters. 149 | 150 | Additional namespace bindings are added by the XSLT to the context node for '`array`', '`map`'... prefixes. The XSLT converts the result of an `xsl:evaluate` intruction to the XML representation for JSON by applying templates to the result. The `JSON XML` is then converted to JSON using the `xml-to-json` XPath function. 151 | 152 | Prior to evaluation, the XSLT separates any XPath Prolog from the expression. If a variable assignment is found in the prolog, the `ixsl:call` extension function is used to invoke a `setVariable` function on a JavaScript object passed as an XSLT parameter via the API. 153 | 154 | `ixsl:get` and `ixsl:call` extension functions are used on the JavaScript object passed as an XSLT parameter to fetch the set of variables added to the Notexbook context by evaluation of previous Code cells. 155 | 156 | # XPath Code Editing Features 157 | 158 | All XPath code editing features are provided by DeltaXignia's companion [XSLT/XPath for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=deltaxml.xslt-xpath) extension - installed automatically with the XPath Notebook extension. 159 | 160 | For documentation on XPath editing features, see the extensions documentation at: [Editing XSLT/XPath](https://deltaxml.github.io/vscode-xslt-xpath/editing-xslt.html) 161 | 162 | # Commands 163 | 164 | | Command | Key-Binding | Details | 165 | | ------- | ------- | --------- | 166 | | New XPath Notebook | - | Creates and opens an untitled notebook file 167 | | XML: Goto XPath | - | Initially shows current XPath at the text prompt | 168 | | XML: Select current element | ⇧⌘0 | Includes start/end tags | 169 | | XML: Select parent element | ⇧⌘9 | Includes start/end tags | 170 | | XML: Select child element | ⇧⌘8 | Includes start/end tags | 171 | | XML: Select following element | ⇧⌘7 | Includes start/end tags | 172 | | XML: Select preceding element | ⇧⌘6 | Includes start/end tags | 173 | 174 | # XPath Notebook Samples 175 | 176 | An Introduction Notebook sample in the code repository at: [notebooks/introduction/xpath-notebook.xbook](https://github.com/DeltaXML/vscode-xpath-notebook/blob/main/notebooks/introduction/xpath-notebook.xbook) 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /resources/xslt/xpath-eval-to-json.xsl: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 48 | 49 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 121 | 122 | 123 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /resources/xslt-sef/xpath-eval-to-json.sef.json: -------------------------------------------------------------------------------- 1 | {"N":"package","version":"30","packageVersion":"1","saxonVersion":"SaxonJS 2.7","target":"JS","targetVersion":"2","name":"TOP-LEVEL","relocatable":"false","buildDateTime":"2025-02-08T10:34:54.765Z","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","C":[{"N":"co","id":"0","uniform":"true","binds":"5 9 3 24 11 8 15","C":[{"N":"template","flags":"os","module":"xpath-eval-to-json.xsl","slots":"200","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","name":"Q{}main","line":"92","expand-text":"true","sType":"* ","C":[{"N":"let","var":"Q{}expressionParts","slot":"0","sType":"* ","line":"93","role":"body","C":[{"N":"ufCall","name":"Q{com.functions.ext}extractPreamble","coId":"5","sType":"*AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"93","bSlot":"0","C":[{"N":"gVarRef","name":"Q{}expression","bSlot":"1"}]},{"N":"let","var":"Q{}preamble","slot":"1","sType":"* ","line":"94","C":[{"N":"check","card":"1","sType":"1AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}preamble\"","role":"select","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}preamble\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}preamble\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}preamble\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"first","sType":"?","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"94","C":[{"N":"varRef","name":"Q{}expressionParts","slot":"0"}]}]}]}]}]}]},{"N":"let","var":"Q{}preambleParts","slot":"2","sType":"* ","line":"95","C":[{"N":"fn","name":"tokenize","sType":"*AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"95","C":[{"N":"treat","as":"AS","diag":"0|0||tokenize","C":[{"N":"check","card":"?","diag":"0|0||tokenize","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||tokenize","C":[{"N":"check","card":"?","diag":"0|0||tokenize","C":[{"N":"data","diag":"0|0||tokenize","C":[{"N":"varRef","name":"Q{}preamble","slot":"1"}]}]}]}]}]},{"N":"str","val":"\\s*=\\s*"}]},{"N":"let","var":"Q{}assignVarName","slot":"3","sType":"* ","line":"96","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}assignVarName\"","role":"select","C":[{"N":"check","card":"?","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}assignVarName\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}assignVarName\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"choose","sType":"?","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"96","C":[{"N":"and","C":[{"N":"compareToInt","op":"eq","val":"2","C":[{"N":"fn","name":"count","C":[{"N":"varRef","name":"Q{}preambleParts","slot":"2"}]}]},{"N":"compareToString","op":"eq","val":"variable","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","C":[{"N":"atomSing","diag":"1|0||vc","card":"?","C":[{"N":"first","C":[{"N":"varRef","name":"Q{}preambleParts","slot":"2"}]}]}]}]},{"N":"subscript","flags":"p","C":[{"N":"varRef","name":"Q{}preambleParts","slot":"2"},{"N":"int","val":"2"}]},{"N":"true"},{"N":"empty"}]}]}]}]}]},{"N":"let","var":"Q{}cleanedExpression","slot":"4","sType":"* ","line":"97","C":[{"N":"check","card":"1","sType":"1AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}cleanedExpression\"","role":"select","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}cleanedExpression\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}cleanedExpression\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}cleanedExpression\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"subscript","flags":"p","sType":"?","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"97","C":[{"N":"varRef","name":"Q{}expressionParts","slot":"0"},{"N":"int","val":"2"}]}]}]}]}]}]},{"N":"let","var":"Q{}result","slot":"5","sType":"* ","line":"98","C":[{"N":"ufCall","name":"Q{com.functions.ext}evaluate","coId":"3","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"98","bSlot":"2","C":[{"N":"gVarRef","name":"Q{}sourceDoc","bSlot":"3"},{"N":"treat","as":"AS","diag":"0|1||ext:evaluate","C":[{"N":"check","card":"1","diag":"0|1||ext:evaluate","C":[{"N":"cvUntyped","to":"AS","diag":"0|1||ext:evaluate","C":[{"N":"check","card":"1","diag":"0|1||ext:evaluate","C":[{"N":"data","diag":"0|1||ext:evaluate","C":[{"N":"varRef","name":"Q{}cleanedExpression","slot":"4"}]}]}]}]}]}]},{"N":"sequence","sType":"* ","C":[{"N":"choose","sType":"* ","line":"100","C":[{"N":"varRef","name":"Q{}assignVarName","slot":"3","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"100"},{"N":"ifCall","name":"Q{http://saxonica.com/ns/interactiveXSLT}call","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"101","C":[{"N":"gVarRef","name":"Q{}this","bSlot":"4"},{"N":"str","val":"setVariable"},{"N":"arrayBlock","C":[{"N":"varRef","name":"Q{}assignVarName","slot":"3"},{"N":"varRef","name":"Q{}result","slot":"5"}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"ifCall","name":"Q{http://saxonica.com/ns/interactiveXSLT}call","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"103","C":[{"N":"gVarRef","name":"Q{}this","bSlot":"4"},{"N":"str","val":"setVariable"},{"N":"arrayBlock","C":[{"N":"str","val":"_"},{"N":"varRef","name":"Q{}result","slot":"5"}]}]},{"N":"let","var":"Q{}jsonXML","slot":"6","sType":"*AS ","line":"104","C":[{"N":"choose","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"104","C":[{"N":"fn","name":"exists","C":[{"N":"varRef","name":"Q{}result","slot":"5"}]},{"N":"ufCall","name":"Q{com.functions.ext}convertArrayEntry","coId":"8","bSlot":"5","C":[{"N":"varRef","name":"Q{}result","slot":"5"}]},{"N":"true"},{"N":"gVarRef","name":"Q{}emptyArrayXML","bSlot":"6"}]},{"N":"fn","name":"xml-to-json","sType":"?AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"105","C":[{"N":"treat","as":"N","diag":"0|0||xml-to-json","C":[{"N":"check","card":"?","diag":"0|0||xml-to-json","C":[{"N":"varRef","name":"Q{}jsonXML","slot":"6"}]}]}]}]}]}]}]}]}]}]}]}]}]},{"N":"co","id":"1","vis":"PRIVATE","ex:uniform":"true","binds":"10 12 14 13","C":[{"N":"function","name":"Q{com.functions.ext}testSourceURI","as":"* ","slots":"200","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[* ] a[] ","sType":"1F r[* ] a[] ","line":"57","C":[{"N":"choose","sType":"* ","type":"item()*","role":"body","line":"58","C":[{"N":"and","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"59","C":[{"N":"gVarRef","name":"Q{}sourceURI","bSlot":"0"},{"N":"compareToString","op":"ne","val":"undefined","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","C":[{"N":"gVarRef","name":"Q{}sourceURI","bSlot":"0"}]}]},{"N":"try","flags":"r","sType":"* ","C":[{"N":"sequence","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"61","C":[{"N":"gVarRef","name":"Q{}source.xml","bSlot":"1"},{"N":"fn","name":"doc","C":[{"N":"gVarRef","name":"Q{}sourceURI","bSlot":"0"}]}]},{"N":"catch","err":"*","errors":"*","sType":"* ","C":[{"N":"try","flags":"r","sType":"* ","C":[{"N":"sequence","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"64","C":[{"N":"gVarRef","name":"Q{}source.json","bSlot":"2"},{"N":"fn","name":"json-doc","C":[{"N":"gVarRef","name":"Q{}sourceURI","bSlot":"0"}]}]},{"N":"catch","err":"*","errors":"*","sType":"*ADI ","C":[{"N":"sequence","sType":"*ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"65","C":[{"N":"gVarRef","name":"Q{}source.empty","bSlot":"3"},{"N":"empty"}]}]}]}]}]},{"N":"true"},{"N":"sequence","sType":"*ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"71","C":[{"N":"gVarRef","name":"Q{}source.empty","bSlot":"3"},{"N":"empty"}]}]}]}]},{"N":"co","id":"2","vis":"PRIVATE","ex:uniform":"true","binds":"23 12 24 27","C":[{"N":"function","name":"Q{com.functions.ext}createContextElement","as":"1NE ","slots":"200","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[1NE ] a[] ","sType":"1F r[1NE ] a[] ","line":"76","C":[{"N":"check","card":"1","sType":"1NE ","diag":"2|0|XTTE0780|function Q{com.functions.ext}createContextElement()","role":"body","C":[{"N":"treat","as":"NE ","diag":"2|0|XTTE0780|function Q{com.functions.ext}createContextElement()","role":"body","C":[{"N":"check","card":"1","diag":"2|0|XTTE0780|function Q{com.functions.ext}createContextElement()","role":"body","C":[{"N":"choose","sType":"* ","type":"item()*","role":"body","line":"77","C":[{"N":"vc","op":"eq","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"78","C":[{"N":"gVarRef","name":"Q{}sourceType","bSlot":"0"},{"N":"gVarRef","name":"Q{}source.xml","bSlot":"1"}]},{"N":"forEach","sType":"* ","C":[{"N":"check","card":"?","sType":"? ","diag":"2|0|XTTE3180|xsl:copy/@select","role":"select","line":"79","C":[{"N":"docOrder","sType":"*NE","C":[{"N":"slash","op":"/","sType":"*NE","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","C":[{"N":"treat","as":"N","diag":"1|0|XPTY0019|slash","C":[{"N":"gVarRef","name":"Q{}sourceDoc","bSlot":"2"}]},{"N":"axis","name":"child","nodeTest":"*NE"}]}]}]},{"N":"copy","sType":"1 ","flags":"cin","line":"79","C":[{"N":"sequence","sType":"*NN ","C":[{"N":"namespace","sType":"1NN ","C":[{"N":"str","sType":"1AS ","val":"array"},{"N":"str","role":"select","val":"http://www.w3.org/2005/xpath-functions/array","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"80"}]},{"N":"namespace","sType":"1NN ","C":[{"N":"str","sType":"1AS ","val":"map"},{"N":"str","role":"select","val":"http://www.w3.org/2005/xpath-functions/map","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"81"}]},{"N":"namespace","sType":"1NN ","C":[{"N":"str","sType":"1AS ","val":"math"},{"N":"str","role":"select","val":"http://www.w3.org/2005/xpath-functions/math","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"82"}]},{"N":"namespace","sType":"1NN ","C":[{"N":"str","sType":"1AS ","val":"xs"},{"N":"str","role":"select","val":"http://www.w3.org/2001/XMLSchema","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"83"}]}]}]}]},{"N":"true"},{"N":"gVarRef","name":"Q{}nsContextElement","bSlot":"3","sType":"NE ","role":"select","line":"87"}]}]}]}]}]}]},{"N":"co","id":"3","vis":"PRIVATE","ex:uniform":"true","binds":"23 12 21 25 20","C":[{"N":"function","name":"Q{com.functions.ext}evaluate","as":"* ","slots":"202","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[* ] a[* ,1AS ] ","sType":"1F r[* ] a[* ,1AS ] ","line":"108","C":[{"N":"arg","slot":"0","name":"Q{}doc","as":"* ","sType":"* "},{"N":"arg","slot":"1","name":"Q{}xpathText","as":"AS ","sType":"AS "},{"N":"choose","sType":"* ","type":"item()*","role":"body","line":"112","C":[{"N":"vc","op":"eq","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"113","C":[{"N":"gVarRef","name":"Q{}sourceType","bSlot":"0"},{"N":"gVarRef","name":"Q{}source.xml","bSlot":"1"}]},{"N":"evaluate","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~ ex=http://ns.saxonica.com/xslt/export","as":"","sType":"* ","line":"120","C":[{"N":"cast","as":"AS","flags":"a","role":"xpath","C":[{"N":"data","C":[{"N":"varRef","name":"Q{}xpathText","slot":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"xpath","line":"120"}]}]},{"N":"str","sType":"1AS ","role":"sa","val":"no"},{"N":"varRef","name":"Q{}doc","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"cxt","line":"120"},{"N":"gVarRef","name":"Q{}xpathVariableMap","bSlot":"2","sType":"FM ","role":"wp","line":"120"},{"N":"gVarRef","name":"Q{}contextNsDoc","bSlot":"3","sType":"NE ","role":"nsCxt","line":"120"},{"N":"fn","name":"string-join","sType":"1AS ","role":"baseUri","C":[{"N":"convert","type":"AS*","from":"AZ","to":"AS","C":[{"N":"data","C":[{"N":"mergeAdj","sType":"AS ","C":[{"N":"gVarRef","name":"Q{}staticBaseURI","bSlot":"4","sType":"AS ","line":"120"}]}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"evaluate","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~ ex=http://ns.saxonica.com/xslt/export","as":"","sType":"* ","line":"128","C":[{"N":"cast","as":"AS","flags":"a","role":"xpath","C":[{"N":"data","C":[{"N":"varRef","name":"Q{}xpathText","slot":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"xpath","line":"128"}]}]},{"N":"str","sType":"1AS ","role":"sa","val":"no"},{"N":"varRef","name":"Q{}doc","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"cxt","line":"128"},{"N":"gVarRef","name":"Q{}xpathVariableMap","bSlot":"2","sType":"FM ","role":"wp","line":"128"},{"N":"fn","name":"string-join","sType":"1AS ","role":"baseUri","C":[{"N":"convert","type":"AS*","from":"AZ","to":"AS","C":[{"N":"data","C":[{"N":"mergeAdj","sType":"AS ","C":[{"N":"gVarRef","name":"Q{}staticBaseURI","bSlot":"4","sType":"AS ","line":"128"}]}]}]},{"N":"str","sType":"1AS ","val":" "}]}]}]}]}]},{"N":"co","binds":"","id":"4","vis":"PRIVATE","ex:uniform":"true","C":[{"N":"function","name":"Q{com.functions.ext}getURItoPrefixMap","as":"1FM ","slots":"201","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[1FM ] a[1N ] ","sType":"1F r[1FM ] a[1N ] ","line":"133","C":[{"N":"arg","slot":"0","name":"Q{}source","as":"N ","sType":"N "},{"N":"treat","as":"FM ","diag":"2|0|XTTE0780|function Q{com.functions.ext}getURItoPrefixMap()","role":"body","C":[{"N":"check","card":"1","diag":"2|0|XTTE0780|function Q{com.functions.ext}getURItoPrefixMap()","role":"body","C":[{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}merge","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"body","line":"142","C":[{"N":"treat","as":"FM","diag":"0|0||map:merge","C":[{"N":"for","name":"Q{}pfx","slot":"21","C":[{"N":"fn","name":"in-scope-prefixes","C":[{"N":"treat","as":"NE","diag":"0|0||in-scope-prefixes","C":[{"N":"check","card":"1","diag":"0|0||in-scope-prefixes","C":[{"N":"varRef","name":"Q{}source","slot":"0"}]}]}]},{"N":"for","name":"Q{}ns","slot":"22","C":[{"N":"fn","name":"namespace-uri-for-prefix","C":[{"N":"varRef","name":"Q{}pfx","slot":"21"},{"N":"treat","as":"NE","diag":"0|1||namespace-uri-for-prefix","C":[{"N":"check","card":"1","diag":"0|1||namespace-uri-for-prefix","C":[{"N":"varRef","name":"Q{}source","slot":"0"}]}]}]},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}entry","C":[{"N":"varRef","name":"Q{}ns","slot":"22"},{"N":"varRef","name":"Q{}pfx","slot":"21"}]}]}]}]}]}]}]}]}]},{"N":"co","id":"5","vis":"PRIVATE","ex:uniform":"true","binds":"16 17 18","C":[{"N":"function","name":"Q{com.functions.ext}extractPreamble","as":"*AS ","slots":"201","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[*AS ] a[1AS ] ","sType":"1F r[*AS ] a[1AS ] ","line":"145","C":[{"N":"arg","slot":"0","name":"Q{}text","as":"AS ","sType":"AS "},{"N":"treat","as":"AS ","diag":"2|0|XTTE0780|function Q{com.functions.ext}extractPreamble()","role":"body","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0780|function Q{com.functions.ext}extractPreamble()","role":"body","C":[{"N":"data","sType":"*A ","role":"body","C":[{"N":"let","var":"Q{}codepoints","slot":"1","sType":"* ","line":"147","role":"body","C":[{"N":"fn","name":"string-to-codepoints","sType":"*ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"147","C":[{"N":"treat","as":"AS","diag":"0|0||string-to-codepoints","C":[{"N":"check","card":"?","diag":"0|0||string-to-codepoints","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||string-to-codepoints","C":[{"N":"check","card":"?","diag":"0|0||string-to-codepoints","C":[{"N":"data","diag":"0|0||string-to-codepoints","C":[{"N":"varRef","name":"Q{}text","slot":"0"}]}]}]}]}]}]},{"N":"let","var":"Q{}percentPos","slot":"2","sType":"* ","line":"148","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"148","C":[{"N":"fn","name":"index-of","C":[{"N":"data","diag":"0|0||index-of","C":[{"N":"varRef","name":"Q{}codepoints","slot":"1"}]},{"N":"gVarRef","name":"Q{}percentCP","bSlot":"0"},{"N":"str","val":"http://www.w3.org/2005/xpath-functions/collation/codepoint"}]}]},{"N":"let","var":"Q{}singlePos","slot":"3","sType":"* ","line":"149","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"149","C":[{"N":"fn","name":"index-of","C":[{"N":"data","diag":"0|0||index-of","C":[{"N":"varRef","name":"Q{}codepoints","slot":"1"}]},{"N":"gVarRef","name":"Q{}singleQuoteCP","bSlot":"1"},{"N":"str","val":"http://www.w3.org/2005/xpath-functions/collation/codepoint"}]}]},{"N":"let","var":"Q{}doublePos","slot":"4","sType":"* ","line":"150","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"150","C":[{"N":"fn","name":"index-of","C":[{"N":"data","diag":"0|0||index-of","C":[{"N":"varRef","name":"Q{}codepoints","slot":"1"}]},{"N":"gVarRef","name":"Q{}doubleQuoteCP","bSlot":"2"},{"N":"str","val":"http://www.w3.org/2005/xpath-functions/collation/codepoint"}]}]},{"N":"let","var":"Q{}resolvedPos","slot":"5","sType":"* ","line":"152","C":[{"N":"check","card":"?","sType":"?ADI ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}resolvedPos\"","C":[{"N":"treat","as":"ADI ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}resolvedPos\"","C":[{"N":"check","card":"?","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}resolvedPos\"","C":[{"N":"cvUntyped","to":"ADI","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}resolvedPos\"","C":[{"N":"data","sType":"*A ","C":[{"N":"choose","sType":"* ","line":"153","C":[{"N":"fn","name":"exists","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"153","C":[{"N":"varRef","name":"Q{}percentPos","slot":"2"}]},{"N":"let","var":"Q{}minPos","slot":"5","sType":"* ","line":"154","C":[{"N":"check","card":"1","sType":"1ADI ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}minPos\"","role":"select","C":[{"N":"treat","as":"ADI ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}minPos\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}minPos\"","role":"select","C":[{"N":"cvUntyped","to":"ADI","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}minPos\"","role":"select","C":[{"N":"fn","name":"min","sType":"?A","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"154","C":[{"N":"data","diag":"0|0||min","C":[{"N":"sequence","C":[{"N":"varRef","name":"Q{}percentPos","slot":"2"},{"N":"varRef","name":"Q{}singlePos","slot":"3"},{"N":"varRef","name":"Q{}doublePos","slot":"4"}]}]},{"N":"str","val":"http://www.w3.org/2005/xpath-functions/collation/codepoint"}]}]}]}]}]},{"N":"choose","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"155","C":[{"N":"vc","op":"eq","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","C":[{"N":"check","card":"?","diag":"1|0||vc","C":[{"N":"data","diag":"1|0||vc","C":[{"N":"varRef","name":"Q{}percentPos","slot":"2"}]}]},{"N":"check","card":"?","diag":"1|1||vc","C":[{"N":"data","diag":"1|1||vc","C":[{"N":"varRef","name":"Q{}minPos","slot":"5"}]}]}]},{"N":"varRef","name":"Q{}percentPos","slot":"2"},{"N":"true"},{"N":"empty"}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]}]}]}]}]}]},{"N":"let","var":"Q{}preamble","slot":"6","sType":"* ","line":"158","C":[{"N":"choose","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"158","C":[{"N":"varRef","name":"Q{}resolvedPos","slot":"5"},{"N":"fn","name":"normalize-space","C":[{"N":"fn","name":"substring","C":[{"N":"treat","as":"AS","diag":"0|0||substring","C":[{"N":"check","card":"?","diag":"0|0||substring","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||substring","C":[{"N":"check","card":"?","diag":"0|0||substring","C":[{"N":"data","diag":"0|0||substring","C":[{"N":"varRef","name":"Q{}text","slot":"0"}]}]}]}]}]},{"N":"convert","to":"AO","flags":"","C":[{"N":"int","val":"1"}]},{"N":"check","card":"1","diag":"0|2||substring","C":[{"N":"convert","to":"AO","flags":"","C":[{"N":"cvUntyped","to":"AO","diag":"0|2||substring","C":[{"N":"arith","op":"-","calc":"a-a","C":[{"N":"check","card":"?","diag":"1|0||arith","C":[{"N":"data","diag":"1|0||arith","C":[{"N":"varRef","name":"Q{}resolvedPos","slot":"5"}]}]},{"N":"int","val":"1"}]}]}]}]}]}]},{"N":"true"},{"N":"str","val":""}]},{"N":"let","var":"Q{}main","slot":"7","sType":"* ","line":"159","C":[{"N":"check","card":"1","sType":"1AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}main\"","role":"select","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}main\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}main\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0570|xsl:variable name=\"Q{}main\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"choose","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"159","C":[{"N":"varRef","name":"Q{}resolvedPos","slot":"5"},{"N":"fn","name":"substring","C":[{"N":"treat","as":"AS","diag":"0|0||substring","C":[{"N":"check","card":"?","diag":"0|0||substring","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||substring","C":[{"N":"check","card":"?","diag":"0|0||substring","C":[{"N":"data","diag":"0|0||substring","C":[{"N":"varRef","name":"Q{}text","slot":"0"}]}]}]}]}]},{"N":"check","card":"1","diag":"0|1||substring","C":[{"N":"convert","to":"AO","flags":"","C":[{"N":"cvUntyped","to":"AO","diag":"0|1||substring","C":[{"N":"arith","op":"+","calc":"a+a","C":[{"N":"check","card":"?","diag":"1|0||arith","C":[{"N":"data","diag":"1|0||arith","C":[{"N":"varRef","name":"Q{}resolvedPos","slot":"5"}]}]},{"N":"int","val":"1"}]}]}]}]}]},{"N":"true"},{"N":"varRef","name":"Q{}text","slot":"0"}]}]}]}]}]}]},{"N":"sequence","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"160","C":[{"N":"varRef","name":"Q{}preamble","slot":"6"},{"N":"varRef","name":"Q{}main","slot":"7"}]}]}]}]}]}]}]}]}]}]}]}]}]},{"N":"co","id":"6","vis":"PRIVATE","ex:uniform":"true","binds":"28 26","C":[{"N":"function","name":"Q{com.functions.ext}tidyXPath","as":"*AS ","slots":"201","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[*AS ] a[1N ] ","sType":"1F r[*AS ] a[1N ] ","line":"165","C":[{"N":"arg","slot":"0","name":"Q{}node","as":"N ","sType":"N "},{"N":"let","var":"Q{}parts","slot":"1","sType":"*AS ","line":"167","role":"body","C":[{"N":"analyzeString","sType":"*AS ","C":[{"N":"fn","name":"path","sType":"?AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"168","C":[{"N":"treat","as":"N","diag":"0|0||path","C":[{"N":"check","card":"?","diag":"0|0||path","C":[{"N":"varRef","name":"Q{}node","slot":"0"}]}]}]},{"N":"fn","name":"string-join","sType":"1AS ","role":"regex","C":[{"N":"convert","type":"AS*","from":"AZ","to":"AS","C":[{"N":"data","C":[{"N":"mergeAdj","sType":"AS ","C":[{"N":"gVarRef","name":"Q{}regex","bSlot":"0","sType":"AS ","line":"168"}]}]}]},{"N":"str","sType":"1AS ","val":" "}]},{"N":"str","sType":"1AS ","val":"","role":"flags"},{"N":"let","var":"Q{}uri","slot":"1","sType":"*AS ","line":"170","role":"matching","C":[{"N":"fn","name":"substring","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"170","C":[{"N":"treat","as":"AS","diag":"0|0||substring","C":[{"N":"check","card":"?","diag":"0|0||substring","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||substring","C":[{"N":"atomSing","diag":"0|0||substring","card":"?","C":[{"N":"dot"}]}]}]}]},{"N":"convert","to":"AO","flags":"","C":[{"N":"int","val":"3"}]},{"N":"convert","to":"AO","flags":"","C":[{"N":"arith","op":"-","calc":"i-i","C":[{"N":"fn","name":"string-length","C":[{"N":"treat","as":"AS","diag":"0|0||string-length","C":[{"N":"check","card":"?","diag":"0|0||string-length","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||string-length","C":[{"N":"atomSing","diag":"0|0||string-length","card":"?","C":[{"N":"dot"}]}]}]}]}]},{"N":"int","val":"3"}]}]}]},{"N":"let","var":"Q{}pfx","slot":"2","sType":"*AS ","line":"171","C":[{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}get","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"171","C":[{"N":"gVarRef","name":"Q{}xmlnsMap","bSlot":"1"},{"N":"check","card":"1","diag":"0|1||map:get","C":[{"N":"data","diag":"0|1||map:get","C":[{"N":"varRef","name":"Q{}uri","slot":"1"}]}]}]},{"N":"choose","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"172","C":[{"N":"compareToInt","op":"eq","val":"0","C":[{"N":"fn","name":"string-length","C":[{"N":"treat","as":"AS","diag":"0|0||string-length","C":[{"N":"check","card":"?","diag":"0|0||string-length","C":[{"N":"cvUntyped","to":"AS","diag":"0|0||string-length","C":[{"N":"check","card":"?","diag":"0|0||string-length","C":[{"N":"data","diag":"0|0||string-length","C":[{"N":"varRef","name":"Q{}pfx","slot":"2"}]}]}]}]}]}]}]},{"N":"str","val":""},{"N":"true"},{"N":"fn","name":"concat","C":[{"N":"check","card":"?","diag":"undefined|0||concat","C":[{"N":"data","diag":"undefined|0||concat","C":[{"N":"varRef","name":"Q{}pfx","slot":"2"}]}]},{"N":"str","val":":"}]}]}]}]},{"N":"dot","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"nonMatching","line":"175"}]},{"N":"fn","name":"concat","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"179","C":[{"N":"str","val":" "},{"N":"fn","name":"string-join","C":[{"N":"data","diag":"0|0||string-join","C":[{"N":"varRef","name":"Q{}parts","slot":"1"}]}]}]}]}]}]},{"N":"co","id":"7","vis":"PRIVATE","ex:uniform":"true","binds":"29","C":[{"N":"function","name":"Q{com.functions.ext}convertMapEntry","as":"* ","slots":"202","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[* ] a[?AS ,* ] ","sType":"1F r[* ] a[?AS ,* ] ","line":"182","C":[{"N":"arg","slot":"0","name":"Q{}key","as":"?AS ","sType":"?AS "},{"N":"arg","slot":"1","name":"Q{}value","as":"* ","sType":"* "},{"N":"choose","sType":"* ","type":"item()*","role":"body","line":"186","C":[{"N":"compareToInt","op":"gt","val":"1","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"187","C":[{"N":"fn","name":"count","C":[{"N":"varRef","name":"Q{}value","slot":"1"}]}]},{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"188","C":[{"N":"sequence","sType":"* ","C":[{"N":"choose","sType":"? ","line":"189","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"189"},{"N":"att","name":"key","sType":"1NA ","line":"190","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"varRef","sType":"*","name":"Q{}key","slot":"0","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"190"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"forEach","sType":"* ","line":"192","C":[{"N":"varRef","name":"Q{}value","slot":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"192"},{"N":"applyT","sType":"* ","line":"193","mode":"#unnamed","bSlot":"0","C":[{"N":"dot","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"193"}]}]}]}]},{"N":"fn","name":"exists","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"197","C":[{"N":"varRef","name":"Q{}value","slot":"1"}]},{"N":"forEach","sType":"* ","line":"198","C":[{"N":"varRef","name":"Q{}value","slot":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"198"},{"N":"applyT","sType":"* ","line":"199","mode":"#unnamed","bSlot":"0","C":[{"N":"dot","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"199"},{"N":"withParam","name":"Q{}key","slot":"0","sType":"*","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"200"}]}]}]},{"N":"true"},{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"205","C":[{"N":"att","name":"key","nsuri":"","sType":"1NA ","C":[{"N":"fn","name":"string-join","sType":"1AS ","C":[{"N":"convert","type":"AS*","from":"AZ","to":"AS","C":[{"N":"data","C":[{"N":"mergeAdj","sType":"*","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"205"}]}]}]},{"N":"str","sType":"1AS ","val":" "}]}]}]}]}]}]},{"N":"co","id":"8","vis":"PRIVATE","ex:uniform":"true","binds":"29","C":[{"N":"function","name":"Q{com.functions.ext}convertArrayEntry","as":"* ","slots":"201","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"muu","sig":"1F r[* ] a[* ] ","sType":"1F r[* ] a[* ] ","line":"210","C":[{"N":"arg","slot":"0","name":"Q{}value","as":"* ","sType":"* "},{"N":"choose","sType":"* ","type":"item()*","role":"body","line":"212","C":[{"N":"compareToInt","op":"gt","val":"1","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"213","C":[{"N":"fn","name":"count","C":[{"N":"varRef","name":"Q{}value","slot":"0"}]}]},{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"214","C":[{"N":"forEach","sType":"* ","line":"215","C":[{"N":"varRef","name":"Q{}value","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"215"},{"N":"applyT","sType":"* ","line":"216","mode":"#unnamed","bSlot":"0","C":[{"N":"dot","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"216"}]}]}]},{"N":"fn","name":"exists","sType":"1AB","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"220","C":[{"N":"varRef","name":"Q{}value","slot":"0"}]},{"N":"forEach","sType":"* ","line":"221","C":[{"N":"varRef","name":"Q{}value","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"221"},{"N":"applyT","sType":"* ","line":"222","mode":"#unnamed","bSlot":"0","C":[{"N":"dot","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"222"}]}]},{"N":"true"},{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"226","C":[{"N":"empty","sType":"0 "}]}]}]}]},{"N":"co","binds":"","id":"9","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalParam","name":"Q{}expression","sType":"AS ","slots":"200","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"i","as":"AS ","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","C":[{"N":"check","card":"1","sType":"1AS ","diag":"2|0|XTTE0590|globalParam name=\"Q{}expression\"","role":"select","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0590|globalParam name=\"Q{}expression\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0590|globalParam name=\"Q{}expression\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0590|globalParam name=\"Q{}expression\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"empty","sType":"0 ","role":"select"}]}]}]}]}]}]}]},{"N":"co","binds":"","id":"10","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalParam","name":"Q{}sourceURI","sType":"?AS ","slots":"200","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"?AS ","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","C":[{"N":"empty","sType":"0 ","role":"select"}]}]},{"N":"co","binds":"","id":"11","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalParam","name":"Q{}this","sType":" ","slots":"200","module":"xpath-eval-to-json.xsl","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","flags":"i","as":" ","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","C":[{"N":"check","card":"1","sType":"1 ","diag":"2|0|XTTE0590|globalParam name=\"Q{}this\"","role":"select","C":[{"N":"empty","sType":"0 ","role":"select"}]}]}]},{"N":"co","binds":"","id":"12","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}source.xml","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"int","val":"1","sType":"1ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"20"}]}]},{"N":"co","binds":"","id":"13","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}source.empty","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"int","val":"2","sType":"1ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"21"}]}]},{"N":"co","binds":"","id":"14","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}source.json","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"int","val":"3","sType":"1ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"22"}]}]},{"N":"co","binds":"","id":"15","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}emptyArrayXML","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"NE ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"element()","C":[{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","C":[{"N":"empty","sType":"0 "}]}]}]},{"N":"co","binds":"","id":"16","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}percentCP","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"check","card":"1","sType":"1ADI ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}percentCP\"","role":"select","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"25","C":[{"N":"fn","name":"string-to-codepoints","C":[{"N":"str","val":"%"}]}]}]}]}]},{"N":"co","binds":"","id":"17","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}singleQuoteCP","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"check","card":"1","sType":"1ADI ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}singleQuoteCP\"","role":"select","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"26","C":[{"N":"fn","name":"string-to-codepoints","C":[{"N":"str","val":"'"}]}]}]}]}]},{"N":"co","binds":"","id":"18","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}doubleQuoteCP","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"check","card":"1","sType":"1ADI ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}doubleQuoteCP\"","role":"select","C":[{"N":"first","sType":"?ADI","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"27","C":[{"N":"fn","name":"string-to-codepoints","C":[{"N":"str","val":"\""}]}]}]}]}]},{"N":"co","id":"19","vis":"PUBLIC","ex:uniform":"true","binds":"11","C":[{"N":"globalVariable","name":"Q{}xpathVariableNames","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"*","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","C":[{"N":"ifCall","name":"Q{http://saxonica.com/ns/interactiveXSLT}get","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"29","C":[{"N":"gVarRef","name":"Q{}this","bSlot":"0"},{"N":"str","val":"keys"}]}]}]},{"N":"co","id":"20","vis":"PUBLIC","ex:uniform":"true","binds":"11","C":[{"N":"globalVariable","name":"Q{}staticBaseURI","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"AS ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:string","C":[{"N":"check","card":"1","sType":"1AS ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}staticBaseURI\"","role":"select","C":[{"N":"treat","as":"AS ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}staticBaseURI\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|globalVariable name=\"Q{}staticBaseURI\"","role":"select","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}staticBaseURI\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"ifCall","name":"Q{http://saxonica.com/ns/interactiveXSLT}get","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"30","C":[{"N":"gVarRef","name":"Q{}this","bSlot":"0"},{"N":"str","val":"staticBaseURI"}]}]}]}]}]}]}]}]},{"N":"co","id":"21","vis":"PUBLIC","ex:uniform":"true","binds":"19 11","C":[{"N":"globalVariable","name":"Q{}xpathVariableMap","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"FM ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"map(*)","C":[{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}merge","sType":"1FM ","C":[{"N":"forEach","sType":"*FM ","line":"34","C":[{"N":"gVarRef","name":"Q{}xpathVariableNames","bSlot":"0","sType":"*","role":"select","line":"34"},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}entry","sType":"1FM ","C":[{"N":"atomSing","diag":"0|0||map:entry","C":[{"N":"fn","name":"QName","sType":"1AQ","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"35","C":[{"N":"str","val":""},{"N":"treat","as":"AS","diag":"0|1||QName","C":[{"N":"check","card":"1","diag":"0|1||QName","C":[{"N":"cvUntyped","to":"AS","diag":"0|1||QName","C":[{"N":"atomSing","diag":"0|1||QName","C":[{"N":"dot"}]}]}]}]}]}]},{"N":"ifCall","name":"Q{http://saxonica.com/ns/interactiveXSLT}call","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"35","C":[{"N":"gVarRef","name":"Q{}this","bSlot":"1"},{"N":"str","val":"getVariable"},{"N":"arrayBlock","C":[{"N":"dot"}]}]}]}]},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}merge","C":[{"N":"sequence","C":[{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}entry","type":"map()","C":[{"N":"str","role":"key","val":"duplicates"},{"N":"str","val":"reject"}]},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}entry","type":"map()","C":[{"N":"str","role":"key","val":"duplicates-error-code"},{"N":"str","val":"XTDE3365"}]}]}]}]}]}]},{"N":"co","id":"22","vis":"PUBLIC","ex:uniform":"true","binds":"1","C":[{"N":"globalVariable","name":"Q{}testedSourceURIParts","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"*","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"item()*","C":[{"N":"ufCall","name":"Q{com.functions.ext}testSourceURI","coId":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"40","bSlot":"0"}]}]},{"N":"co","id":"23","vis":"PUBLIC","ex:uniform":"true","binds":"22","C":[{"N":"globalVariable","name":"Q{}sourceType","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"ADI ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:integer","C":[{"N":"check","card":"1","sType":"1ADI ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}sourceType\"","role":"select","C":[{"N":"treat","as":"ADI ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}sourceType\"","role":"select","C":[{"N":"check","card":"1","diag":"2|0|XTTE0570|globalVariable name=\"Q{}sourceType\"","role":"select","C":[{"N":"cvUntyped","to":"ADI","sType":"*A ","diag":"2|0|XTTE0570|globalVariable name=\"Q{}sourceType\"","role":"select","C":[{"N":"data","sType":"*A ","role":"select","C":[{"N":"first","sType":"?","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"41","C":[{"N":"gVarRef","name":"Q{}testedSourceURIParts","bSlot":"0"}]}]}]}]}]}]}]}]},{"N":"co","id":"24","vis":"PUBLIC","ex:uniform":"true","binds":"22","C":[{"N":"globalVariable","name":"Q{}sourceDoc","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"?","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"item()*","C":[{"N":"subscript","flags":"p","sType":"?","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"42","C":[{"N":"gVarRef","name":"Q{}testedSourceURIParts","bSlot":"0"},{"N":"int","val":"2"}]}]}]},{"N":"co","id":"25","vis":"PUBLIC","ex:uniform":"true","binds":"2","C":[{"N":"globalVariable","name":"Q{}contextNsDoc","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"NE ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"element()","C":[{"N":"ufCall","name":"Q{com.functions.ext}createContextElement","coId":"2","sType":"1NE","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"44","bSlot":"0"}]}]},{"N":"co","id":"26","vis":"PUBLIC","ex:uniform":"true","binds":"23 12 4 24","C":[{"N":"globalVariable","name":"Q{}xmlnsMap","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"FM ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"map(*)","C":[{"N":"choose","sType":"1FM","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"46","C":[{"N":"vc","op":"eq","comp":"GAC|http://www.w3.org/2005/xpath-functions/collation/codepoint","C":[{"N":"gVarRef","name":"Q{}sourceType","bSlot":"0"},{"N":"gVarRef","name":"Q{}source.xml","bSlot":"1"}]},{"N":"ufCall","name":"Q{com.functions.ext}getURItoPrefixMap","coId":"4","bSlot":"2","C":[{"N":"check","card":"1","diag":"0|0||ext:getURItoPrefixMap","C":[{"N":"slash","op":"/","C":[{"N":"treat","as":"N","diag":"1|0|XPTY0019|slash","C":[{"N":"gVarRef","name":"Q{}sourceDoc","bSlot":"3"}]},{"N":"axis","name":"child","nodeTest":"*NE"}]}]}]},{"N":"true"},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}_new"}]}]}]},{"N":"co","binds":"","id":"27","vis":"PUBLIC","ex:uniform":"false","C":[{"N":"globalVariable","name":"Q{}nsContextElement","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"NE ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"element()","C":[{"N":"elem","name":"root","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}root ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"math=http://www.w3.org/2005/xpath-functions/math","ns":"xml=~ xsl=~ xs=~ array=~ map=~ math=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","line":"54","C":[{"N":"empty","sType":"0 ","ns":"xml=~ xsl=~ xs=~ array=~ map=~ math=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~"}]}]}]},{"N":"co","binds":"","id":"28","vis":"PUBLIC","ex:uniform":"true","C":[{"N":"globalVariable","name":"Q{}regex","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","module":"xpath-eval-to-json.xsl","slots":"200","sType":"AS ","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","as":"xs:string","C":[{"N":"str","val":"Q\\{[^\\{]*\\}","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"163"}]}]},{"N":"co","id":"29","binds":"6","C":[{"N":"mode","onNo":"SC","flags":"","patternSlots":"0","prec":"","C":[{"N":"templateRule","rank":"0","prec":"0","seq":"2","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","minImp":"0","flags":"s","slots":"200","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","line":"257","module":"xpath-eval-to-json.xsl","expand-text":"true","match":".[. instance of array(*)]","prio":"1","matches":"","C":[{"N":"p.booleanExp","role":"match","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","C":[{"N":"fn","name":"exists","C":[{"N":"filter","C":[{"N":"dot"},{"N":"instance","of":"1FA","C":[{"N":"dot"}]}]}]}]},{"N":"sequence","role":"action","sType":"* ","C":[{"N":"param","name":"Q{}key","slot":"0","sType":"?AS ","as":"?AS ","flags":"","line":"258","C":[{"N":"empty","sType":"0 ","role":"select"},{"N":"check","card":"?","sType":"?AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"treat","as":"AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"check","card":"?","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"data","sType":"*A ","role":"conversion","C":[{"N":"supplied","role":"conversion","slot":"0","sType":"* "}]}]}]}]}]}]},{"N":"elem","name":"array","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}array ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"259","C":[{"N":"sequence","sType":"* ","C":[{"N":"choose","sType":"? ","line":"260","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"260"},{"N":"att","name":"key","sType":"1NA ","line":"261","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"varRef","sType":"*","name":"Q{}key","slot":"0","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"261"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/array}for-each","sType":"1FA","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"263","C":[{"N":"treat","as":"FA","diag":"0|0||array:for-each","C":[{"N":"check","card":"1","diag":"0|0||array:for-each","C":[{"N":"dot"}]}]},{"N":"fnRef","name":"Q{com.functions.ext}convertArrayEntry","arity":"1","resultType":"*"}]}]}]}]}]},{"N":"templateRule","rank":"1","prec":"0","seq":"1","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","minImp":"0","flags":"s","slots":"200","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","line":"247","module":"xpath-eval-to-json.xsl","expand-text":"true","match":".[. instance of map(*)]","prio":"1","matches":"","C":[{"N":"p.booleanExp","role":"match","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","C":[{"N":"fn","name":"exists","C":[{"N":"filter","C":[{"N":"dot"},{"N":"instance","of":"1FM","C":[{"N":"dot"}]}]}]}]},{"N":"sequence","role":"action","sType":"* ","C":[{"N":"param","name":"Q{}key","slot":"0","sType":"?AS ","as":"?AS ","flags":"","line":"248","C":[{"N":"empty","sType":"0 ","role":"select"},{"N":"check","card":"?","sType":"?AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"treat","as":"AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"check","card":"?","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"data","sType":"*A ","role":"conversion","C":[{"N":"supplied","role":"conversion","slot":"0","sType":"* "}]}]}]}]}]}]},{"N":"elem","name":"map","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}map ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"249","C":[{"N":"sequence","sType":"* ","C":[{"N":"choose","sType":"? ","line":"250","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"250"},{"N":"att","name":"key","sType":"1NA ","line":"251","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"varRef","sType":"*","name":"Q{}key","slot":"0","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"251"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"ifCall","name":"Q{http://www.w3.org/2005/xpath-functions/map}for-each","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"253","C":[{"N":"treat","as":"FM","diag":"0|0||map:for-each","C":[{"N":"check","card":"1","diag":"0|0||map:for-each","C":[{"N":"dot"}]}]},{"N":"fnCoercer","to":"F a[1A,*] r[*]","diag":"0|1||map:for-each","C":[{"N":"fnRef","name":"Q{com.functions.ext}convertMapEntry","arity":"2","resultType":"*"}]}]}]}]}]}]},{"N":"templateRule","rank":"2","prec":"0","seq":"0","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","minImp":"0","flags":"s","slots":"200","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","line":"237","module":"xpath-eval-to-json.xsl","expand-text":"true","match":".[ . instance of node() or . instance of text() or . instance of attribute() or . instance of processing-instruction() or . instance of comment() ]","prio":"1","matches":"","C":[{"N":"p.booleanExp","role":"match","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","C":[{"N":"fn","name":"exists","C":[{"N":"filter","C":[{"N":"dot"},{"N":"or","C":[{"N":"or","C":[{"N":"or","C":[{"N":"or","C":[{"N":"instance","of":"1N","C":[{"N":"dot"}]},{"N":"instance","of":"1NT","C":[{"N":"dot"}]}]},{"N":"instance","of":"1NA","C":[{"N":"dot"}]}]},{"N":"instance","of":"1NP","C":[{"N":"dot"}]}]},{"N":"instance","of":"1NC","C":[{"N":"dot"}]}]}]}]}]},{"N":"sequence","role":"action","sType":"* ","C":[{"N":"param","name":"Q{}key","slot":"0","sType":"?AS ","as":"?AS ","flags":"","line":"238","C":[{"N":"empty","sType":"0 ","role":"select"},{"N":"check","card":"?","sType":"?AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"treat","as":"AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"check","card":"?","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"data","sType":"*A ","role":"conversion","C":[{"N":"supplied","role":"conversion","slot":"0","sType":"* "}]}]}]}]}]}]},{"N":"elem","name":"string","sType":"1NE nQ{http://www.w3.org/2005/xpath-functions}string ","nsuri":"http://www.w3.org/2005/xpath-functions","namespaces":"","line":"239","C":[{"N":"sequence","sType":"* ","C":[{"N":"choose","sType":"? ","line":"240","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"240"},{"N":"att","name":"key","sType":"1NA ","line":"241","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"varRef","sType":"*","name":"Q{}key","slot":"0","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"241"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"ufCall","name":"Q{com.functions.ext}tidyXPath","coId":"6","sType":"*AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"243","bSlot":"0","C":[{"N":"treat","as":"N","diag":"0|0||ext:tidyXPath","C":[{"N":"check","card":"1","diag":"0|0||ext:tidyXPath","C":[{"N":"dot"}]}]}]}]}]}]}]},{"N":"templateRule","rank":"3","prec":"0","seq":"3","ns":"xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext =http://www.w3.org/2005/xpath-functions ixsl=~","minImp":"0","flags":"s","slots":"200","baseUri":"file:///Users/phil.fearon/Documents/github/vscode-xpath-notebook/resources/xslt/xpath-eval-to-json.xsl","line":"267","module":"xpath-eval-to-json.xsl","expand-text":"true","match":".","prio":"-1","matches":"","C":[{"N":"p.any","role":"match","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ "},{"N":"sequence","role":"action","sType":"* ","C":[{"N":"param","name":"Q{}key","slot":"0","sType":"?AS ","as":"?AS ","flags":"","line":"268","C":[{"N":"empty","sType":"0 ","role":"select"},{"N":"check","card":"?","sType":"?AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"treat","as":"AS ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"check","card":"?","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"cvUntyped","to":"AS","sType":"*A ","diag":"2|1|XTTE0590|xsl:param name=\"Q{}key\"","role":"conversion","C":[{"N":"data","sType":"*A ","role":"conversion","C":[{"N":"supplied","role":"conversion","slot":"0","sType":"* "}]}]}]}]}]}]},{"N":"let","var":"Q{}jsonTypeName","slot":"1","sType":"*NE ","line":"277","C":[{"N":"choose","sType":"1AS","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"277","C":[{"N":"instance","of":"1A m[AO,AD,AF]","C":[{"N":"dot"}]},{"N":"str","val":"number"},{"N":"true"},{"N":"choose","C":[{"N":"instance","of":"1AB","C":[{"N":"dot"}]},{"N":"str","val":"boolean"},{"N":"true"},{"N":"str","val":"string"}]}]},{"N":"compElem","sType":"1NE ","line":"279","C":[{"N":"fn","name":"string-join","sType":"1AS ","role":"name","C":[{"N":"convert","type":"AS*","from":"AZ","to":"AS","C":[{"N":"data","C":[{"N":"mergeAdj","sType":"*","C":[{"N":"varRef","name":"Q{}jsonTypeName","slot":"1","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"279"}]}]}]},{"N":"str","sType":"1AS ","val":" "}]},{"N":"sequence","role":"content","sType":"* ","C":[{"N":"choose","sType":"? ","line":"280","C":[{"N":"varRef","name":"Q{}key","slot":"0","sType":"*","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","line":"280"},{"N":"att","name":"key","sType":"1NA ","line":"281","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"varRef","sType":"*","name":"Q{}key","slot":"0","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"281"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"true"},{"N":"empty","sType":"0 "}]},{"N":"valueOf","flags":"l","sType":"1NT ","line":"283","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"forEach","sType":"*AS ","C":[{"N":"data","sType":"*A ","C":[{"N":"mergeAdj","C":[{"N":"dot","sType":"1","ns":"= xml=~ xsl=~ xs=~ array=~ map=~ ext=com.functions.ext ixsl=~ ","role":"select","line":"283"}]}]},{"N":"fn","name":"string","sType":"1AS ","C":[{"N":"dot"}]}]},{"N":"str","sType":"1AS ","val":" "}]}]}]}]}]}]}]}]}]},{"N":"overridden"},{"N":"output","C":[{"N":"property","name":"Q{http://saxon.sf.net/}stylesheet-version","value":"30"},{"N":"property","name":"method","value":"text"},{"N":"property","name":"indent","value":"no"}]},{"N":"decimalFormat"}],"Σ":"26b2a871"} --------------------------------------------------------------------------------