Added XSLT transformations

This commit is contained in:
Michael Szul 2018-12-12 13:48:20 -05:00
parent 84adff578f
commit f295059159
12 changed files with 1715 additions and 1676 deletions

3176
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@
"url": "https://github.com/DotJoshJohnson/vscode-xml/issues"
},
"engines": {
"vscode": "^1.22.2"
"vscode": "^1.29.0"
},
"categories": [
"Formatters",
@ -36,6 +36,7 @@
"onCommand:xmlTools.executeXQuery",
"onCommand:xmlTools.formatAsXml",
"onCommand:xmlTools.minifyXml",
"onCommand:xmlTools.runXSLTTransform",
"onLanguage:xml",
"onLanguage:xquery",
"onLanguage:xsl"
@ -62,6 +63,10 @@
{
"command": "xmlTools.minifyXml",
"title": "XML Tools: Minify XML"
},
{
"command": "xmlTools.runXSLTTransform",
"title": "XML Tools: Run XSLT Transformation"
}
],
"configuration": {
@ -250,11 +255,12 @@
"@types/xmldom": "^0.1.29",
"tslint": "^5.9.1",
"typescript": "^2.6.1",
"vscode": "^1.1.16"
"vscode": "^1.1.26"
},
"dependencies": {
"xmldom": "^0.1.27",
"xpath": "0.0.27",
"xqlint": "^0.4.1"
"xqlint": "^0.4.1",
"xslt-processor": "^0.11.1"
}
}

View file

@ -4,6 +4,7 @@ export namespace commands {
export const formatAsXml = "xmlTools.formatAsXml";
export const getCurrentXPath = "xmlTools.getCurrentXPath";
export const minifyXml = "xmlTools.minifyXml";
export const runXSLTTransform = "xmlTools.runXSLTTransform";
}
export namespace contextKeys {

View file

@ -11,6 +11,7 @@ import { XQueryLinter } from "./linting";
import { XmlTreeDataProvider } from "./tree-view";
import { evaluateXPath, getCurrentXPath } from "./xpath/commands";
import { executeXQuery } from "./xquery-execution/commands";
import { runXSLTTransform } from "./xslt";
import * as constants from "./constants";
@ -48,7 +49,7 @@ export function activate(context: ExtensionContext) {
});
if (Configuration.enableXmlTreeViewCursorSync) {
window.onDidChangeTextEditorSelection(x => {
window.onDidChangeTextEditorSelection((x: any) => {
if (x.kind === TextEditorSelectionChangeKind.Mouse && x.selections.length > 0) {
treeView.reveal(treeViewDataProvider.getNodeAtPosition(x.selections[0].start));
}
@ -69,6 +70,11 @@ export function activate(context: ExtensionContext) {
context.subscriptions.push(
commands.registerTextEditorCommand(constants.commands.executeXQuery, executeXQuery)
);
/* XSLT Transformation Features */
context.subscriptions.push(
commands.registerCommand(constants.commands.runXSLTTransform, runXSLTTransform)
);
}
export function deactivate() {

View file

@ -1,10 +1,11 @@
import * as assert from "assert";
import { FormattingOptions } from "vscode";
import { TestDataLoader } from "./test-utils/test-data-loader";
import { XmlFormatter, XmlFormattingOptions } from "../formatting";
import { V2XmlFormatter } from "../formatting/formatters";
import { readFileSync } from "fs";
import { XSLTTransform } from "../xslt/xslt-transform";
describe("V2XmlFormatter", () => {
@ -91,6 +92,13 @@ describe("V2XmlFormatter", () => {
it("should support mixed content", () => {
testFormatter(xmlFormatter, options, "issue-200");
});
it("show transform XML to XSLT", () => {
assert.doesNotThrow(() => {
const xml = TestDataLoader.load("xslt-transform.xml");
const xslt = TestDataLoader.load("xslt-transform.xsl");
new XSLTTransform(xml, xslt).apply();
});
});
});

View file

@ -0,0 +1,48 @@
<schedule>
<week>
<weektext>Orientation Week 1</weektext>
<start_date>2018-07-30</start_date>
<end_date>2018-08-11</end_date>
<events>
<event>
<event_id>2317</event_id>
<day>Sunday</day>
<start_date_time>2018-08-06T07:30:00</start_date_time>
<end_date_time>2018-08-06T12:00:00</end_date_time>
<length>270</length>
<event_title>Training</event_title>
<short_name>Training</short_name>
<instances>
<instance>
<start_date_time>2018-08-06T07:30:00</start_date_time>
<end_date_time>2018-08-06T12:00:00</end_date_time>
<room>See Course Website</room>
<instructors>
<instructor>... TBA</instructor>
</instructors>
</instance>
</instances>
</event>
<event>
<event_id>2316</event_id>
<day>Sunday</day>
<start_date_time>2018-08-06T08:10:00</start_date_time>
<end_date_time>2018-08-06T12:00:00</end_date_time>
<length>230</length>
<event_title>Challenge Course</event_title>
<short_name>Challenge</short_name>
<instances>
<instance>
<start_date_time>2018-08-06T08:10:00</start_date_time>
<end_date_time>2018-08-06T12:00:00</end_date_time>
<room>See Course Website</room>
<instructors>
<instructor>Person One</instructor>
<instructor>Person Two</instructor>
</instructors>
</instance>
</instances>
</event>
</events>
</week>
</schedule>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="/">
<div>
<table>
<xsl:for-each select="/schedule/week">
<xsl:sort select="weektext"/>
<tr><td colspan="4"><xsl:value-of select="weektext"/></td></tr>
<xsl:for-each select="events/event">
<xsl:sort select="events/event/start_date_time" type="datetime"/>
<tr>
<td>
<xsl:value-of select="FormattedDate"/>
</td>
<td>
<xsl:value-of select="event_title"/>
</td>
<td>
<xsl:value-of select="length"/> minutes
</td>
<td>
<a href="Activity?EventID={event_id}">details...</a>
</td>
</tr>
<tr>
<td colspan="4">
<table>
<xsl:for-each select="instances/instance">
<tr>
<td>
<xsl:value-of select="start_date_time_formatted"/>
</td>
<td>
<xsl:value-of select="end_date_time_formatted"/>
</td>
<td>
<xsl:value-of select="room"/>
</td>
<td>
<xsl:apply-templates select="instructors/instructor"
/>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</div>
</xsl:template>
<xsl:template match="instructor">
<xsl:text>, </xsl:text>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="instructor[1]">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>

View file

@ -37,10 +37,10 @@ export class XmlTreeDataProvider implements TreeDataProvider<any> {
const enableMetadata = Configuration.enableXmlTreeViewMetadata;
const enableSync = Configuration.enableXmlTreeViewCursorSync;
const treeItem = new TreeItem(element.localName);
const treeItem = new TreeItem((<Element>element).localName);
if (!this._xmlTraverser.isElement(element)) {
treeItem.label = `${element.localName} = "${element.nodeValue}"`;
treeItem.label = `${(<Element>element).localName} = "${element.nodeValue}"`;
}
else if (enableMetadata) {

2
src/xslt/index.ts Normal file
View file

@ -0,0 +1,2 @@
export * from "./xslt-apply";
export * from "./xslt-transform";

1
src/xslt/schema.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module 'xslt-processor';

39
src/xslt/xslt-apply.ts Normal file
View file

@ -0,0 +1,39 @@
import { readFileSync } from "fs";
import { window, workspace, ViewColumn } from "vscode";
import { XSLTTransform } from "./xslt-transform";
export async function runXSLTTransform () {
const xsltFile = await window.showOpenDialog(
{
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
filters: {
"XSLT" : ["xsl", "xslt"]
}
}
);
if (window.activeTextEditor !== undefined && xsltFile !== undefined) {
const xml = window.activeTextEditor.document.getText();
const xslt = readFileSync(xsltFile[0].fsPath).toString();
try {
const result = new XSLTTransform(xml, xslt).apply();
const textDoc = await workspace.openTextDocument({
content: result,
language: "xml"
});
window.showTextDocument(textDoc, ViewColumn.Beside);
const web = window.createWebviewPanel("transformPreview", "XSLT Results", ViewColumn.Beside, { });
web.webview.html = result;
}
catch (e) {
window.showErrorMessage(e);
}
}
else {
window.showErrorMessage("An error occurred while accessing the XML and/or XSLT source files.");
}
}

View file

@ -0,0 +1,18 @@
import { xmlParse, xsltProcess } from "xslt-processor";
export class XSLTTransform {
private _xml: string;
private _xslt: string;
constructor(xml: string, xslt: string) {
this._xml = xml;
this._xslt = xslt;
}
public apply(): string {
try {
return xsltProcess(xmlParse(this._xml), xmlParse(this._xslt));
}
catch (e) {
throw new Error(e);
}
}
}