我正在尝试转换一个看起来像这样的xml文档:
<CData>
<Description>whatever</Description>
<Property>
<SetValue>123</SetValue>
<Description>whatever</Description>
<DefaultValue>321</DefaultValue>
</Property>
<Property>
<SetValue>999</SetValue>
<Description>whatever</Description>
<DefaultValue>721</DefaultValue>
</Property>
</CData>
每个CData标记都是一个表,属性标记表示一个表行。现在,如果单个Property标签具有Default和SetValue,并且它们不同,我需要检查每个CDate标签。这背后的原因是我只想要DefaultValue和SetValue不同的表。这是检查工作正常:
<xsl:for-each select="CData">
<xsl:for-each select="Property">
<xsl:if test="SetValue">
<xsl:if test="SetValue/text()!=''">
<xsl:if test="DefaultValue">
<xsl:if test="SetValue!=DefaultValue">
//SET a Value
</xsl:if
</xsl:if>
<xsl:if test="not(DefaultValue)">
//SET a VALUE
</xsl:if>
</xsl:if>
</xsl:if>
</xsl:for-each>
在这个检查中,我需要一个变量,如果条件为真,将设置变量,在此for-each循环之后,我想用if-tag检查变量,如果设置了,我想打印一个表。我现在唯一的问题是我不知道如何在循环中设置一个变量,我可以像全局变量一样使用。
答案 0 :(得分:2)
这不是XSLT的工作方式 - 所有变量都是词法范围的,一旦创建变量就不能改变变量的值。
您需要稍微考虑一下这个问题。而不是循环的“程序”视图,逐个测试条件并设置标志,你需要更多地以声明的方式思考 - 使用谓词来选择你感兴趣的节点:
<!-- this variable will contain only the Property elements that have a SetValue
and a DefaultValue that are different -->
<xsl:variable name="interestingProperties"
select="CData/Property[SetValue != DefaultValue]" />
然后根据是否选择了任何节点采取措施:
<xsl:if test="$interestingProperties">
<table>
<xsl:for-each select="$interestingProperties">
<tr>...</tr>
</xsl:for-each>
</table>
</xsl:if>
如果您想允许不拥有DefaultValue
的Property元素,那么您可以稍微更改谓词:
<!-- this variable will contain only the Property elements that have a SetValue
and do not also have a DefaultValue which matches it -->
<xsl:variable name="interestingProperties"
select="CData/Property[SetValue][not(SetValue = DefaultValue)]" />
这里我使用的是not(X = Y)
而不是X != Y
,因为当您处理可能包含零个或多个成员的节点集时,语义会略有不同。基本上SetValue != DefaultValue
说“有一对SetValue
和一个DefaultValue
元素使得它们的值不同”(特别是这意味着必须至少有一个用于测试成功),而not(SetValue = DefaultValue)
表示“不存在匹配的SetValue
和DefaultValue
对”(如果SetValue
或DefaultValue
或[SetValue]
遗失了,所以我们还需要一个单独的{{1}}来确保它存在。)