我想使用Saxon XSLT3流功能将不同的tansformation应用于大型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”的特定标签上我正在应用一个java函数。如果我有超过9“xsl:template”,则不会修改输出,也不会调用我的java函数。我没有错误消息
EDIT2:如果我用例如“concat(current(),'_ ID')”替换对java函数的调用,我有相同的行为,所以这不是特定于java函数all。
Aadita:
以下是输入数据示例:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<row>
<id>10</id>
<email>[email protected]</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>[email protected]</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>
我使用以下命令行运行:
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条规则匹配相同的节点类型/节点名称组合(在本例中为所有文本节点),Saxon-EE会尝试通过查找规则子集的条件来避免对所有规则进行线性搜索共同分享。在这种情况下,它正在查看是否可以根据基于文本节点的父节点的前提条件对规则进行分组。
在这个阶段,逻辑存在缺陷;它仔细地确定每个规则是一组1(没有两个父条件是相同的),这应该意味着它然后放弃优化尝试。但它并没有抛弃它;它继续。这应该没关系,因为优化应该正常工作,即使它没有意义。
优化无法正常工作的原因是因为在xsl:apply-templates的流路径上,用于评估规则前置条件的上下文数据未正确初始化,导致规则匹配器认为前提条件不满足。
因此,当规则全部匹配具有相同节点类型和节点名称的节点时,如果您在流模式下拥有一组10个或更多模板规则,那么您就会遇到一个错误。
运行未经许可绕过该错误有两个原因:它停用规则链的优化,并停用流。
要解决此问题,只需从每个模板规则中删除/text()
即可。
在这里记录为一个错误:https://saxonica.plan.io/issues/3901
除非您另有说明,否则我将根据您的测试数据和样式表向XSLT 3.0的W3C测试套件提交一个新的测试用例。