Saxon-JS 处理包含元素的 CDATA 是不是存在已知错误

Posted

技术标签:

【中文标题】Saxon-JS 处理包含元素的 CDATA 是不是存在已知错误【英文标题】:Is there a known error of Saxon-JS handling CDATA containing elementsSaxon-JS 处理包含元素的 CDATA 是否存在已知错误 【发布时间】:2018-07-29 01:57:47 【问题描述】:

我想知道 Saxon-JS 处理包含 CDATA 元素的方式是否存在已知错误。

我有一个有效的 XSLT 3.0 和 XML 流程,其中包括从包含 CDATA 的元素中获取文本并在转换中应用 html 标记。我会尝试在不发布脚本的情况下提出问题。

我正在使用 Saxon-HE 9.8.0.3 并尝试使用最新的 Saxon-JS。 从 .xsl 文件转换为 .sef 文件的所有内容都有效,但从包含 CDATA 的元素中获取的文本的预期格式除外。

我有一个元素 <docText>,它只包含 <![CDATA[ ... ]]> 封闭的多行文本。

我用类似这样的方式调用模板: <xsl:apply-templates select="ancestor::document/docText"/>

我匹配<xsl:template match="docText/text()">

对包含在变量中的<docText> 中的文本的最终操作输出如下: <xsl:value-of select="$step9-2" disable-output-escaping="yes" />

同样,当我从 Java 的命令行中使用 Saxon-HE、XML 和 XSLT 3.0 的原始转换时,输出是正确的 HTML 标记。与 Saxon-JS 一起使用的转换脚本几乎相同,除了最初在 CDATA 部分中的文本格式外,所有逻辑都有效。文本已输出,但未格式化。

是否有任何原因导致错误可能是由于 Saxon-JS 处理 CDATA 部分的方式与 Saxon-HE 处理的方式不同?

迈克尔

【问题讨论】:

我想知道它是否像您想象的那样是 CDATA 部分,或者仅仅是使用disable-output-escaping。您如何将 XSLT 3 与 Saxon-JS 一起使用,是否有任何 API 用于您序列化结果以便disable-output-escaping 可以产生任何影响? 我的 XSLT 大部分是 2.0,但我在样式表中声明了 version="3.0"。也许我应该提到我将已修改为与 Saxon-JS 一起使用的 .xsl 文件转换为带有 OxygenXML 19.1 的 .sef 文件。如果不发布所有代码,也许只有 Saxon 开发人员才能回答。感谢您的意见。 【参考方案1】:

见http://www.saxonica.com/saxon-js/documentation/index.html#!conformance/xslt30说

Saxon-JS 没有实现以下可选特性 规范:模式感知、序列化、流式传输、 高阶函数和禁用输出转义

【讨论】:

我没有注意到 Saxon-JS 网站上发布的排除功能。但是,我不确定这是唯一的问题。我没有看到证据表明我上面列出的来自docText 的调用甚至与模板docText/text() 匹配。我通过从我的工作解决方案中删除匹配的模板进行了测试,并获得了类似的文本连接。无论如何,您在上面指出的排除至少让我知道我需要寻找不同的解决方案。谢谢你的时间。 内置模板规则将处理您自己的模板未处理的任何docText 元素的子节点,然后文本节点的内置模板将输出文本节点。因此,鉴于您迄今为止发布的信息以及 Saxon-JS 的限制,结果似乎符合预期。你在 CDATA 部分有什么样的上下文,你不能用parse-xml-fragment 将它解析成节点并用xsl:copy-ofxsl:sequence 输出它们吗? 我之前已经发布了我的上下文,您已经做出了一些有用的详细回复。我的 CDATA 包含带有有限标记的纯文本,由行尾、括号格式标记/单词和偶尔的 HTML 标记指示。使用您之前建议的解决方案,我通常可以完成大约 80% 的工作,但最终总是会遇到一些我似乎无法通过的步骤。我的转换基于内容创建 HTML 文档和 ePub。有时我可能会再做一次。我确实尝试过<xsl:value-of select="parse-xml-fragment($step9-2)/*" /> 代替我第一次发布的那一行。不过还是谢谢。 好吧,xsl:value-of 永远不会创建任何元素节点,即使你设法将标记解析为元素节点,所以如果你想输出元素,你将不得不使用 xsl:copy-ofxsl:sequence节点。如果标记不是 XML,因此 parse-xmlparse-xml-fragment 不起作用,那么正如 Michael 指出的那样,在 Saxon-JS 中,您可以调用 javascript,其中 DOMParser 用于完整文档或 Range.createContextualFragment 允许您解析HTML 标记字符串。 我已经尝试从 Saxon-JS 调用 Javascript 来使用createContextualFragment,一个例子在martin-honnen.github.io/xslt/2018/test201802190101.html,文件的源代码在github.com/martin-honnen/martin-honnen.github.io/blob/master/…和github.com/martin-honnen/martin-honnen.github.io/blob/master/…在线。 HTH【参考方案2】:

是的,有一个已知问题:https://saxonica.plan.io/issues/3385

没有看到您的更多代码,我不确定该问题是否相关。该错误表示,如果有任何空白剥离有效,则 CDATA 部分将转换为文本节点,否则不会,因此一个有用的实验是看看如果您添加到样式表会发生什么

<xsl:strip-space elements="a-dummy-element-name"/>

这将触发空白剥离,这也具有将 CDATA 节点转换为普通文本节点的效果。

但是,这并不能解决您的代码依赖于禁用输出转义的问题。如果您的 CDATA/text 节点包含需要复制到 HTML 页面中的 HTML 标记,那么在 Saxon-JS 下执行此操作的唯一方法是将 HTML 解析为节点树,并将节点添加到 HTML DOM。如果 HTML 是格式良好的 XML,您可以使用 parse-xml() 函数来执行此操作;如果没有,您可能需要调用 Javascript。

【讨论】:

我会检查空格剥离的情况。无论如何,如果不完全重写我现在拥有的工作代码,我可能不会在不禁用输出转义的情况下获得所需的输出。我的主要目标是使用表单来输入我之前使用 Saxon-HE 在命令行中输入的参数。这就是我想试验 Saxon-JS 的原因。由于您和 Martin 指出的原因,我没有从 CDATA 部分开始的内容中获取格式,但它确实有效。感谢您的回复。

以上是关于Saxon-JS 处理包含元素的 CDATA 是不是存在已知错误的主要内容,如果未能解决你的问题,请参考以下文章

PHP处理XML文档,没有CDATA部分数据处理

Mybatis中的CDATA标签

Saxon-js 是不是对 xsl:param 执行 XML 语法检查?

mapper中的CDATA标签的用法

Mybatis中的CDATA标签的用法

XSD - 如何使一个元素包含 CDATA 标签?