Saxon-EE XSLT v3 Streaming 有任何限制吗?

Any limitation with Saxon-EE XSLT v3 Streaming?

我想使用 Saxon XSLT3 流功能将不同的转换应用到大型 XML 文档。我面临的问题是,如果我应用此转换 它不起作用:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ano contextutil"  xmlns:ano="java:StreamingGenericProcessor"
  xmlns:contextutil="java:GenericAnonymizerContextUtil">
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:param name="context" as="class:java.lang.Object" xmlns:class="http://saxon.sf.net/java-type"/>
 <xsl:template match="internal/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="ano:uuid($context, current(), 'ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

但是这个确实如此:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ano contextutil"  xmlns:ano="java:StreamingGenericProcessor"
  xmlns:contextutil="java:GenericAnonymizerContextUtil">
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:param name="context" as="class:java.lang.Object" xmlns:class="http://saxon.sf.net/java-type"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="ano:uuid($context, current(), 'ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

我测试了很多不同的场景,我得出结论,如果我有超过 9 个 "xsl:template",它就不起作用!

编辑: 它不起作用意味着:在名为 "id" 的特定标签上我' m 应用 java 函数。如果我有超过 9 个 "xsl:template",则不会修改输出并且根本不会调用我的 java 函数。我没有错误信息

EDIT2: 如果我将对 java 函数的调用替换为例如, "concat(current(), '_ID')",我有相同的行为,所以这不是 java 函数特有的。

EDIT3:

这是一个示例输入数据:

<?xml version="1.0" encoding="UTF-8"?>
<table>
  <row>
    <id>10</id>
    <email>fake@fake.com</email>
    <address>dsffe</address>
    <birthday>10/2018</birthday>
    <country>FR</country>
    <external>zz</external>
    <internal>ww</internal>
    <name>Jean</name>
    <phone>000000</phone>
    <city>Dfegd</city>
  </row>
  <row>
    <id>9</id>
    <email>fake@fake2.com</email>
    <address>sdfzefzef</address>
    <birthday>11/2012</birthday>
    <country>GB</country>
    <external>xx</external>
    <internal>yy</internal>
    <name>Jean-Claude</name>
    <phone>000000</phone>
    <city>dd</city>
  </row>

这个始终有效的 xsl:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="concat(current(), '_ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

有问题的那个(同一个xsl多了一个模板):

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="internal/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="concat(current(), '_ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

I 运行 使用以下命令行:

java -cp Saxon-EE-9.8.0-14.jar  net.sf.saxon.Transform -s:test.xml -xsl:concat_not_working.xsl

工作 XSL 正确地将 _ID 附加到输出 id 标记值,而 不工作 xsl 不做任何转换。

另一个信息,如果我 运行 没有许可证(所以没有流媒体),两个样式表都可以工作!

我正在使用带有试用许可证的 Saxon-EE 9.8.0-14:这可能是一个未记录的试用许可证限制吗?

您关于 10 条或更多规则会发生故障的理论被证明是正确的。当超过 10 个规则匹配相同的 node-kind/node-name 组合(在本例中为所有文本节点)时,Saxon-EE 会尝试通过查找规则子集共享的条件来避免对所有规则进行线性搜索常见的。在这种情况下,它正在查看是否可以根据基于文本节点父级的前提条件对规则进行分组。

现阶段逻辑有问题;它仔细计算出每个规则都在一组 1(没有两个父条件相同),这应该意味着它随后放弃了优化尝试。但它并没有放弃它;它继续。这应该无关紧要,因为优化应该可以正常工作,即使它毫无意义。

优化无法正常工作的原因是因为在 xsl:apply-模板的流路径上,用于评估规则前提条件的上下文数据未正确初始化,导致规则匹配器认为前提条件不满足。

所以你遇到了一个错误,正如你所猜测的那样,当你在流模式下有一组 10 个或更多的模板规则时,当所有规则都匹配具有相同节点类型和节点的节点时,该错误适用。名字.

运行 unlicensed 绕过这个错误有两个原因:它停用了规则链的优化,它停用了流。

作为解决方法,只需从每个模板规则中删除 /text()

在此处记录为错误:https://saxonica.plan.io/issues/3901

除非您另有说明,否则我将根据您的测试数据和样式表向 XSLT 3.0 的 W3C 测试套件提交一个新的测试用例。