从 JavaScript 调用 Saxon-JS 函数或模板
Calling Saxon-JS function or template from JavaScript
我使用 C3 在使用 Saxon-JS 和(已编译,SEF)XSL 样式表的 HTML 页面中呈现图表。
C3生成SVG图片(条形图),并提供了响应点击事件的可能性(比如条形图),带有onclick函数。
c3.generate(
{ bindto: ...
, data:
{ type: 'bar'
, columns: c3_columns
, onclick: function(data, element) { ... }
}
...
})
我想在我的 XSL 样式表中处理点击事件。
然而:
onclick 函数不是通常意义上的JavaScript 事件处理程序。 data
参数包含数据但不是 Event
实例。另外,JavaScript event
变量在body的onclick函数中是undefined
。
当我从 onclick 函数发送 custom event 时,我无法在我的 XSL 中处理它。这意味着当我定义 <xsl:template match="*" mode="ixsl:onchartclick">
时,当我从 onclick 函数调度 chartclick
事件时不会调用此模板。
接下来,我尝试调用 XSL 样式表中定义的函数:
<xsl:function xmlns:chart="chart" name="chart:click">
这是从 onclick 函数 (JavaScript) 中调用的,例如
SaxonJS.XPath.evaluate("chart:click('hello chartCLick')", [],
{ namespaceContext: {'chart' : 'chart'}
});
虽然调用了onclick函数,但没有调用XSL函数;我在浏览器控制台中得到的只是“未知函数 Q{chart}click()”。
这个场景有点复杂,但我将包括两个简化的代码示例,希望能展示我正在尝试做的事情。
在 Javascript 我有 onclick 处理程序。
function chartClickHandler(data, element) {
// Show the contents of the data.
console.log(`Click on chart`);
Object.entries(data).forEach(([k, v]) => console.log(` ${k} : ${v}`));
// Send a custom event.
const event = new CustomEvent('chartclick', data);
document.getElementsByTagName('body')[0].dispatchEvent(event);
// Call a function in the XSL stylesheet.
SaxonJS.XPath.evaluate(`chart:click('hello chartCLick')`, [],
{ namespaceContext: {'chart' : 'chart'}
});
}
这是从 HTML 调用的。为简单起见,我不使用 C3,但是:
<button onclick="chartClickHandler({x: 1, y: 2}, this)">test</button>
在提供给 Saxon-JS 的 XSL 样式表中,我有:
<xsl:template match="body" mode="ixsl:onchartclick">
<xsl:if test="$show-debug-messages">
<xsl:message>
Chartclick event properties: <xsl:value-of select="ixsl:eval('Object.keys') => ixsl:apply([ixsl:event()])"/>
</xsl:message>
</xsl:if>
</xsl:template>
<xsl:function xmlns:chart="chart" name="chart:click">
<xsl:param name="data"/>
<xsl:message>
Chart click data: <xsl:value-of select="serialize($data)"/>
</xsl:message>
</xsl:function>
如前所述,我得到的只是
Click on chart debugger eval code:3:11
x : 1 debugger eval code:4:52
y : 2 debugger eval code:4:52
Uncaught
Object { message: "Unknown function Q{chart}click()", stack: ...
这个例子还是涉及到很多部分,但是我的问题的本质在标题中:
如何从 JavaScript 调用 Saxon-JS 函数或模板。或者如何拦截自定义事件。
正如我在评论中所说,我认为要在 SEF 中调用函数,您应该使用 SaxonJS.transform({ initialFunction : 'Q{namespace-uri}function-name', functionParams: [function arguments here], ..}, ..)
。
例如https://martin-honnen.github.io/xslt/2022/xsltFunctionCallTest2.html
内容:
<html lang="en">
<head>
<title>Saxon-JS 2 test</title>
<script src="../../Saxon-JS-2.3/SaxonJS2.rt.js"></script>
<script>
var internalStylesheet;
document.addEventListener('DOMContentLoaded', e => {
var options = {
stylesheetLocation : 'xsltFunctionCallTest1.xsl.sef.json',
sourceLocation: 'sample1.xml',
destination: 'appendToBody'
};
SaxonJS.transform(options, 'async').then(result => { internalStylesheet = result.stylesheetInternal; console.log(internalStylesheet); console.log(result); });
});
</script>
<script>
function functionCallTest1() {
SaxonJS.transform({ destination: 'raw', stylesheetLocation : 'xsltFunctionCallTest1.xsl.sef.json', initialFunction: 'Q{http://example.com/mf}f1', functionParams: [ { x: 1, y: 'foo' }] }, 'async').then(result => console.log(result.principalResult));
}
</script>
</head>
<body>
<h1>Test</h1>
</body>
</html>
第一个转换生成的地方,例如
<section>
<h2>Test</h2>
<p>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</p>
<input type="button" value="test"
onclick="functionCallTest1();"/>
</section>
警告:在 XSLT 中,确保您在 XSLT xsl:function
上声明了 visibility="public"
。
我使用 C3 在使用 Saxon-JS 和(已编译,SEF)XSL 样式表的 HTML 页面中呈现图表。 C3生成SVG图片(条形图),并提供了响应点击事件的可能性(比如条形图),带有onclick函数。
c3.generate(
{ bindto: ...
, data:
{ type: 'bar'
, columns: c3_columns
, onclick: function(data, element) { ... }
}
...
})
我想在我的 XSL 样式表中处理点击事件。 然而:
onclick 函数不是通常意义上的JavaScript 事件处理程序。
data
参数包含数据但不是Event
实例。另外,JavaScriptevent
变量在body的onclick函数中是undefined
。当我从 onclick 函数发送 custom event 时,我无法在我的 XSL 中处理它。这意味着当我定义
<xsl:template match="*" mode="ixsl:onchartclick">
时,当我从 onclick 函数调度chartclick
事件时不会调用此模板。接下来,我尝试调用 XSL 样式表中定义的函数:
<xsl:function xmlns:chart="chart" name="chart:click">
这是从 onclick 函数 (JavaScript) 中调用的,例如SaxonJS.XPath.evaluate("chart:click('hello chartCLick')", [], { namespaceContext: {'chart' : 'chart'} });
虽然调用了onclick函数,但没有调用XSL函数;我在浏览器控制台中得到的只是“未知函数 Q{chart}click()”。
这个场景有点复杂,但我将包括两个简化的代码示例,希望能展示我正在尝试做的事情。
在 Javascript 我有 onclick 处理程序。
function chartClickHandler(data, element) {
// Show the contents of the data.
console.log(`Click on chart`);
Object.entries(data).forEach(([k, v]) => console.log(` ${k} : ${v}`));
// Send a custom event.
const event = new CustomEvent('chartclick', data);
document.getElementsByTagName('body')[0].dispatchEvent(event);
// Call a function in the XSL stylesheet.
SaxonJS.XPath.evaluate(`chart:click('hello chartCLick')`, [],
{ namespaceContext: {'chart' : 'chart'}
});
}
这是从 HTML 调用的。为简单起见,我不使用 C3,但是:
<button onclick="chartClickHandler({x: 1, y: 2}, this)">test</button>
在提供给 Saxon-JS 的 XSL 样式表中,我有:
<xsl:template match="body" mode="ixsl:onchartclick">
<xsl:if test="$show-debug-messages">
<xsl:message>
Chartclick event properties: <xsl:value-of select="ixsl:eval('Object.keys') => ixsl:apply([ixsl:event()])"/>
</xsl:message>
</xsl:if>
</xsl:template>
<xsl:function xmlns:chart="chart" name="chart:click">
<xsl:param name="data"/>
<xsl:message>
Chart click data: <xsl:value-of select="serialize($data)"/>
</xsl:message>
</xsl:function>
如前所述,我得到的只是
Click on chart debugger eval code:3:11
x : 1 debugger eval code:4:52
y : 2 debugger eval code:4:52
Uncaught
Object { message: "Unknown function Q{chart}click()", stack: ...
这个例子还是涉及到很多部分,但是我的问题的本质在标题中: 如何从 JavaScript 调用 Saxon-JS 函数或模板。或者如何拦截自定义事件。
正如我在评论中所说,我认为要在 SEF 中调用函数,您应该使用 SaxonJS.transform({ initialFunction : 'Q{namespace-uri}function-name', functionParams: [function arguments here], ..}, ..)
。
例如https://martin-honnen.github.io/xslt/2022/xsltFunctionCallTest2.html
内容:
<html lang="en">
<head>
<title>Saxon-JS 2 test</title>
<script src="../../Saxon-JS-2.3/SaxonJS2.rt.js"></script>
<script>
var internalStylesheet;
document.addEventListener('DOMContentLoaded', e => {
var options = {
stylesheetLocation : 'xsltFunctionCallTest1.xsl.sef.json',
sourceLocation: 'sample1.xml',
destination: 'appendToBody'
};
SaxonJS.transform(options, 'async').then(result => { internalStylesheet = result.stylesheetInternal; console.log(internalStylesheet); console.log(result); });
});
</script>
<script>
function functionCallTest1() {
SaxonJS.transform({ destination: 'raw', stylesheetLocation : 'xsltFunctionCallTest1.xsl.sef.json', initialFunction: 'Q{http://example.com/mf}f1', functionParams: [ { x: 1, y: 'foo' }] }, 'async').then(result => console.log(result.principalResult));
}
</script>
</head>
<body>
<h1>Test</h1>
</body>
</html>
第一个转换生成的地方,例如
<section>
<h2>Test</h2>
<p>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</p>
<input type="button" value="test"
onclick="functionCallTest1();"/>
</section>
警告:在 XSLT 中,确保您在 XSLT xsl:function
上声明了 visibility="public"
。