XSL中有没有办法更新全局变量?
我想检查一下我已经转变过的元素并采取相应的行动。这将要求我以某种方式将元素的名称添加到某种列表中,并在每次转换新元素时更新它。
但是,由于xsl:variable
在某种意义上并不是“可变的”,所以我无法在定义之后添加任何内容。
我有多个包含的数据文件,因此使用仅知道当前节点集的xsl函数将无济于事。
==编辑==
这就是我现在的转型。但它会包含每次在不同子文件中重复引用的文件。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- include the contents of referenced files -->
<xsl:template match="reference">
<xsl:apply-templates select="document(@url)/data/node()" />
</xsl:template>
</xsl:transform>
数据文件看起来像这样:
<data>
<reference url="another_data_file.xml"/>
... other stuff ...
</data>
答案 0 :(得分:7)
XSLT是一种函数式语言,不允许更新变量。如果需要通过多个步骤聚合结果,通常的方法是使用递归模板。例如:
<xsl:template name="transform-elements">
<xsl:param name="elements-to-process" select="/.."/>
<xsl:param name="processed-elements" select="/.."/>
<xsl:if test="$elements-to-process">
<xsl:variable name="element" select="$elements-to-process[1]"/>
<!-- ... Do stuff with $element ...-->
<!-- Recursively invoke template for remaining elements -->
<xsl:call-template name="transform-elements">
<xsl:with-param name="elements-to-process"
select="$elements-to-process[position() != 1]"/>
<xsl:with-param name="processed-elements"
select="$processed-elements|$element"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
答案 1 :(得分:1)
可悲的是,没有直接的方法,XSL变量只有一次分配,但可以有条件地分配。
但是,块中定义的变量只能被该块及其子块访问,可能反转逻辑并迭代地执行它会改变吗?
这样,您就无法处理已经转换的内容,因为它已经完成了。
查看xsl:Key和xsl:for-each的用法,这将允许您对转换的节点进行排序。
引用w3schools,使用此XML:
<persons>
<person name="Tarzan" id="050676"/>
<person name="Donald" id="070754"/>
<person name="Dolly" id="231256"/>
</persons>
这个XSL:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="preg" match="person" use="@id"/>
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="key('preg','050676')">
<p>
Id: <xsl:value-of select="@id"/><br />
Name: <xsl:value-of select="@name"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
将找到ID为“050676”的人。 也许使用这个方法和更明确的键可以为您提供所需的结构?
答案 2 :(得分:1)
如果您的输入数据分布在多个文档中,那么将转换过程分成几个步骤可能是个好主意。
添加预处理转换,将输入文档中的相关部分拉入单个中间文档。然后可以使用简单的XSLT转换此文档,您可能不会遇到您当前面临的问题。
答案 3 :(得分:0)
我不确定您要解析的文档的大小,但作为相对较小的XML文档的解决方案,您可以将结果输出到变量并应用扩展函数 node-set (来自exslt或msxsl等)将变换应用于变量的内容,不包括重复的节点,就像处理单个XML文档一样。