你能在 Saxon-Js 中提供集合查找器吗,还是我找错人了?
Can you provide collection finders in Saxon-Js, or am I barking up the wrong tree?
我正尝试在命令行上 运行 saxon-js 应用 XSL 3 转换,该转换目前在另一个系统中使用 Saxon HE,因为 saxon-js 看起来可以提供更多的多功能性。
我基本上是 XSL 的新手,所以学习曲线很陡峭。
我目前卡住的错误是:
Transformation failure: Error FODC0002 at iati.xslt#90
Unknown collection (no collectionFinder supplied)
触发此事件的 XSLT 片段是:
<xsl:variable name="iati-codelists">
<codes version="2.03">
<xsl:apply-templates select="collection('../lib/schemata/2.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
</xsl:variable>
这打算转到该目录并清除一组 .xml 文件。
查看 saxon-js 文档,我看不到提供集合查找器的选项。
这是在 Saxon HE(目前正在做这项工作)中实现的,而不是在 Saxon-Js 中实现的吗?还是我在咆哮一棵不同但同样错误的树?
谢谢!
是的,你可以。但是,collectionFinder 似乎不能异步工作,因此如果您正在编写异步应用程序,它就不是很有用。
我能够通过对我的节点应用程序中的 collections() 中提供的路径进行一些硬编码来实现这一点,作为概念证明。绝对是更好的方法。
如果这是你的XML
<xsl:variable name="iati-codelists">
<codes version="2.03">
<xsl:apply-templates select="collection('../lib/schemata/2.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="2.02">
<xsl:apply-templates select="collection('../lib/schemata/2.02/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="2.01">
<xsl:apply-templates select="collection('../lib/schemata/2.01/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.05">
<xsl:apply-templates select="collection('../lib/schemata/1.05/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.04">
<xsl:apply-templates select="collection('../lib/schemata/1.04/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.03">
<xsl:apply-templates select="collection('../lib/schemata/1.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
</xsl:variable>
在转换运行之前,这段代码创建了一个集合对象。这些键是代码列表目录文件路径的一部分,其中包含一系列 xml 文档。这些值是 xml 文档的数组,使用 SaxonJS.getResource() 转换为 Saxon JS 需要的格式。在对象中包含 Promises 有点棘手,所以我不得不使用 Lodash。
const _ = require('lodash');
const fs = require('fs');
const fsPromises = fs.promises;
const SaxonJS = require('saxon-js');
// load codelists since collectionFinder can't be async
let codelistPaths = [
"non-embedded-codelist/",
"2.03/codelist/",
"2.02/codelist/",
"2.01/codelist/",
"1.05/codelist/",
"1.04/codelist/",
"1.03/codelist/"
];
// this returns an object of the codelistPaths as Keys and an Array of resolved promises for the Values. these promises are grabbing the codelist XML files using SaxonJS.getResource
let resources = _.zipObject(codelistPaths, await Promise.all(_.map(codelistPaths, async (path) => {
let files = await fsPromises.readdir("./IATI-Rulesets/lib/schemata/" + path);
return await Promise.all(files.map(async (file) => {
return await SaxonJS.getResource({ type : 'xml', file : "./IATI-Rulesets/lib/schemata/" + path + file })
}))
})))
// this pulls the right array of SaxonJS resources from the resources object
const collectionFinder = (url) => {
if (url.includes("codelist")) {
let path = url.split('schemata/')[1].split('?')[0]; // get the right filepath (remove file:// and after the ?
return resources[path]
} else {
return []
}
}
// Applying the XSLT3 Ruleset to IATI Files Using SaxonJS
let results = await SaxonJS.transform({
stylesheetFileName: "path to your .sef.json",
sourceFileName: "path to your input .xml",
destination: "serialized",
collectionFinder: collectionFinder
}, "async")
Saxon-JS 支持论坛中的完整详细信息:
https://saxonica.plan.io/issues/4797?pn=1#change-16579
我正尝试在命令行上 运行 saxon-js 应用 XSL 3 转换,该转换目前在另一个系统中使用 Saxon HE,因为 saxon-js 看起来可以提供更多的多功能性。
我基本上是 XSL 的新手,所以学习曲线很陡峭。
我目前卡住的错误是:
Transformation failure: Error FODC0002 at iati.xslt#90 Unknown collection (no collectionFinder supplied)
触发此事件的 XSLT 片段是:
<xsl:variable name="iati-codelists">
<codes version="2.03">
<xsl:apply-templates select="collection('../lib/schemata/2.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
</xsl:variable>
这打算转到该目录并清除一组 .xml 文件。
查看 saxon-js 文档,我看不到提供集合查找器的选项。
这是在 Saxon HE(目前正在做这项工作)中实现的,而不是在 Saxon-Js 中实现的吗?还是我在咆哮一棵不同但同样错误的树?
谢谢!
是的,你可以。但是,collectionFinder 似乎不能异步工作,因此如果您正在编写异步应用程序,它就不是很有用。
我能够通过对我的节点应用程序中的 collections() 中提供的路径进行一些硬编码来实现这一点,作为概念证明。绝对是更好的方法。
如果这是你的XML
<xsl:variable name="iati-codelists">
<codes version="2.03">
<xsl:apply-templates select="collection('../lib/schemata/2.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="2.02">
<xsl:apply-templates select="collection('../lib/schemata/2.02/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="2.01">
<xsl:apply-templates select="collection('../lib/schemata/2.01/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
<xsl:apply-templates select="collection('../lib/schemata/non-embedded-codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.05">
<xsl:apply-templates select="collection('../lib/schemata/1.05/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.04">
<xsl:apply-templates select="collection('../lib/schemata/1.04/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
<codes version="1.03">
<xsl:apply-templates select="collection('../lib/schemata/1.03/codelist/?select=*.xml;recurse=yes')" mode="get-codelists"/>
</codes>
</xsl:variable>
在转换运行之前,这段代码创建了一个集合对象。这些键是代码列表目录文件路径的一部分,其中包含一系列 xml 文档。这些值是 xml 文档的数组,使用 SaxonJS.getResource() 转换为 Saxon JS 需要的格式。在对象中包含 Promises 有点棘手,所以我不得不使用 Lodash。
const _ = require('lodash');
const fs = require('fs');
const fsPromises = fs.promises;
const SaxonJS = require('saxon-js');
// load codelists since collectionFinder can't be async
let codelistPaths = [
"non-embedded-codelist/",
"2.03/codelist/",
"2.02/codelist/",
"2.01/codelist/",
"1.05/codelist/",
"1.04/codelist/",
"1.03/codelist/"
];
// this returns an object of the codelistPaths as Keys and an Array of resolved promises for the Values. these promises are grabbing the codelist XML files using SaxonJS.getResource
let resources = _.zipObject(codelistPaths, await Promise.all(_.map(codelistPaths, async (path) => {
let files = await fsPromises.readdir("./IATI-Rulesets/lib/schemata/" + path);
return await Promise.all(files.map(async (file) => {
return await SaxonJS.getResource({ type : 'xml', file : "./IATI-Rulesets/lib/schemata/" + path + file })
}))
})))
// this pulls the right array of SaxonJS resources from the resources object
const collectionFinder = (url) => {
if (url.includes("codelist")) {
let path = url.split('schemata/')[1].split('?')[0]; // get the right filepath (remove file:// and after the ?
return resources[path]
} else {
return []
}
}
// Applying the XSLT3 Ruleset to IATI Files Using SaxonJS
let results = await SaxonJS.transform({
stylesheetFileName: "path to your .sef.json",
sourceFileName: "path to your input .xml",
destination: "serialized",
collectionFinder: collectionFinder
}, "async")
Saxon-JS 支持论坛中的完整详细信息: https://saxonica.plan.io/issues/4797?pn=1#change-16579