如何基于条件在XSLT中包装节点?优化现有实现方案
优化XSLT条件包裹节点的代码(消除重复)
需求
当city节点的name属性值为Venezia时,将生成的CityName节点包裹在myCity元素内;其他情况直接输出CityName节点。目前已实现功能,但CityName的代码存在重复,需要更简洁的实现方式(除了创建模板调用外的方案)。
输入XML
<cities> <city name="Milano"/> <city name="Paris"/> <city name="Munchen"/> <city name="Lyon"/> <city name="Venezia"/> </cities>
现有XSLT(存在代码重复)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="city"> <xsl:choose> <xsl:when test="@name='Venezia'"> <myCity> <CityName> <xsl:value-of select="@name"/> </CityName> </myCity> </xsl:when> <xsl:otherwise> <CityName> <xsl:value-of select="@name"/> </CityName> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Identity Transform--> <xsl:template match="node()"> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*"/> </xsl:stylesheet>
期望输出
<cities> <CityName>Milano</CityName> <CityName>Paris</CityName> <CityName>Munchen</CityName> <CityName>Lyon</CityName> <myCity> <CityName>Venezia</CityName> </myCity> </cities>
优化方案(利用模板匹配优先级,无代码重复)
通过拆分两个匹配模板消除重复,利用XSLT中更具体的模板匹配优先级更高的特性,完全避免代码冗余:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配name为Venezia的city节点,输出带myCity包裹的结构 --> <xsl:template match="city[@name='Venezia']"> <myCity> <CityName> <xsl:value-of select="@name"/> </CityName> </myCity> </xsl:template> <!-- 匹配其他所有city节点,直接输出CityName --> <xsl:template match="city"> <CityName> <xsl:value-of select="@name"/> </CityName> </xsl:template> <!-- 身份转换模板 --> <xsl:template match="node()"> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*"/> </xsl:stylesheet>
补充:单模板内的紧凑写法(若接受命名模板)
如果不想拆分模板,也可以提取重复逻辑为命名模板,减少代码重复:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="city"> <xsl:choose> <xsl:when test="@name='Venezia'"> <myCity> <xsl:call-template name="city-name"/> </myCity> </xsl:when> <xsl:otherwise> <xsl:call-template name="city-name"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="city-name"> <CityName> <xsl:value-of select="@name"/> </CityName> </xsl:template> <!-- 身份转换模板 --> <xsl:template match="node()"> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*"/> </xsl:stylesheet>
注:第一种拆分匹配模板的方案更贴合需求,无需额外模板调用,完全依赖XSLT自身的匹配机制实现条件区分,逻辑清晰且无冗余。
内容的提问来源于stack exchange,提问作者asb
相关产品推荐
相关产品推荐

