如何在带条件逻辑的xsl:variable中保留元素属性?
XSLT中带条件逻辑的节点变量赋值问题
原始数据
<mydoc> <setting>foo</setting> <foo sound="aaaa"/> <bar sound="brrr"/> <cat sound="meow"/> </mydoc>
无条件逻辑的场景
直接通过select属性指定节点路径,就能获取带属性的完整元素节点,后续可直接访问其属性或子节点:
<xsl:variable name="result1" select="/mydoc/foo"/>
比如可以用$result1/@sound获取该元素的sound属性值。
带条件逻辑的需求
当需要根据setting的值动态选择节点时,原写法的变量无法像result1一样直接作为节点使用:
<xsl:variable name="result2"> <xsl:choose> <xsl:when test="/mydoc/setting='foo'"> <!-- 此处应编写什么代码 --> </xsl:when> <xsl:when test="/mydoc/setting='cat'"> <!-- 此处应编写什么代码 --> </xsl:when> <xsl:otherwise> <!-- 此处应编写什么代码 --> </xsl:otherwise> </xsl:choose> </xsl:variable>
期望效果:
- 当
setting = 'foo'时,result2指向<foo sound="aaaa"/> - 当
setting = 'cat'时,result2指向<cat sound="meow"/> - 其他情况,
result2指向<bar sound="brrr"/>
解决方案
方案1:XSLT 2.0+ 版本
使用<xsl:sequence>直接引用原文档中的节点,变量会存储原始元素节点而非生成新节点:
<xsl:variable name="result2" as="element()"> <xsl:choose> <xsl:when test="/mydoc/setting='foo'"> <xsl:sequence select="/mydoc/foo"/> </xsl:when> <xsl:when test="/mydoc/setting='cat'"> <xsl:sequence select="/mydoc/cat"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="/mydoc/bar"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
通过as="element()"指定变量类型为元素节点,之后即可像result1一样使用,比如$result2/@sound。
方案2:XSLT 1.0 版本
XSLT1.0不支持<xsl:sequence>,可通过节点集的条件筛选实现:
<xsl:variable name="settingVal" select="/mydoc/setting/text()"/> <xsl:variable name="result2" select="/mydoc/foo[$settingVal='foo'] | /mydoc/cat[$settingVal='cat'] | /mydoc/bar[not($settingVal='foo' or $settingVal='cat')]"/>
通过管道符|组合不同条件的节点筛选结果,变量result2直接指向符合条件的原始节点,可直接访问其属性。
若一定要用<xsl:choose>结构,需借助EXSLT的node-set()函数将结果树片段转换为节点集(需处理器支持EXSLT扩展):
<!-- 需在XSLT开头声明命名空间:xmlns:exsl="http://exslt.org/common" --> <xsl:variable name="result2Temp"> <xsl:choose> <xsl:when test="/mydoc/setting='foo'"> <xsl:copy-of select="/mydoc/foo"/> </xsl:when> <xsl:when test="/mydoc/setting='cat'"> <xsl:copy-of select="/mydoc/cat"/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="/mydoc/bar"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="result2" select="exsl:node-set($result2Temp)/*"/>
内容的提问来源于stack exchange,提问作者toddmo
相关产品推荐
相关产品推荐

