我正在尝试使用Perl执行XSLT 1.0转换。我使用此处列出的solution作为我的脚本。
我的输入xml文件看起来有点像这样。
<?xml version="1.0" encoding="UTF-8" ?>
<bsg>
<msg>
<entry key="testingString">This is a test.</entry>
<!-- <trs> This is me, trs!!! </trs> -->
</msg>
</bsg>
trs
属性是可选的,意味着它并不总是存在于所有其他entry
节点中。
条目可以有可选的属性tslate
,可以是true
或false
,即输入xml文件可以有类似的内容
<entry key="Doctor" tslate="false">Physician.</entry>
在Perl脚本中,我提供了xslt文件,该文件导入了另外两个xslt文件(比如文件A和文件B),这些文件定义了变量和模板。
文件A从输入xml文件读取节点并执行以下操作
<xsl:param name="isOTHERFILEavailable"/>
<xsl:variable name="tvariables">
<xsl:choose>
<xsl:when test="$isOTHERFILEavailable = 'true'">
<xsl:copy-of select="document($OTHERTHE_File)/bsg/msg"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
isOTHERFILEavailable
是从Perl文件传递的字符串参数,用于验证OTHERFILE
是否存在。
然后访问此tvariables
以在文件B中执行一些其他操作,如下所示
<xsl:template match="msg">
<xsl:variable name="trsExists">
<xsl:for-each select="entry">
<xsl:variable name="current_key" select="@key"/>
<xsl:variable name="trsMatch" select="$tvariables/msg/entry[@key = $current_key]"/>
<xsl:choose>
<xsl:when test="$trsMatch and normalize-space($trsMatch/text) = normalize-space(.) and (not(@tslate) or @tslate = true())">
<xsl:copy>
<xsl:copy-of select="$trsMatch/@key|$trsMatch/tvariables/text()|@context"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
</xsl:template>
我的问题是,当我到达这一行时,
<xsl:variable name="trsMatch" select="$tvariables/msg/entry[@key = $current_key]"/>
Perl错误如下
Invalid type
runtime error: file B.xslt line # element variable
Failed to evaluate the expression of variable 'tvariables'
我错过了一些明显的东西吗?
P.S =&gt;使用XSLT 2.0(Saxon)从Java运行相同的转换时,即使未定义tvariables
,也就是isOTHERFILEavailable
为false
时,一切运行正常。
答案 0 :(得分:1)
$ tvariable是一个xml片段。
Perl似乎正在使用XSL 1.0处理器。在这种情况下,您的问题是$ tvariable将需要从片段转换为节点集,然后才能使用它。 XSL 2正如您所期望的那样处理片段,这就是代码在Saxon中运行的原因。 Fortunaltely大多数XSL 1.0处理器(前置全部?)为具有扩展功能的片段提供支持。您需要查看文档以获取详细信息。 您的select语句将变为:
select="node-set($tvariables)/msg/entry[@key = $current_key]"
有关节点集功能的详细信息,请查看http://www.xml.com/pub/a/2003/07/16/nodeset.html。