代码之家  ›  专栏  ›  技术社区  ›  asb

根据条件在xslt元素内换行节点

  •  0
  • asb  · 技术社区  · 3 年前

    我必须有条件地将某些节点封装在另一个元素中。在下面的例子中,如果城市是威尼斯,我需要将CityName包装在MyCity中。我现在已经做到了,但我认为有更好的方法可以在不重复节点的情况下写这篇文章。一种方法是创建一个模板并为CityName调用它,但有没有更优雅的方法可以减少代码行数?

    输入

    <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>
    
    3 回复  |  直到 3 年前
        1
  •  2
  •   y.arazim    3 年前

    我认为您所需要的只是:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
        <xsl:template match="city[@name='Venezia']">
            <myCity>
                <xsl:next-match/>
            </myCity>
        </xsl:template>
        
        <xsl:template match="city">
            <CityName>
                <xsl:value-of select="@name"/>
            </CityName>
        </xsl:template>
        
       <!-- Identity Transform-->
        <xsl:template match="node()">
            <xsl:copy>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>
        </xsl:template>
        
    </xsl:stylesheet>
    
        2
  •  1
  •   Martin Honnen    3 年前

    使用XSLT3可以归结为

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="3.0"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="#all"
      expand-text="yes">
      
      <xsl:template match="city[@name]">
        <CityName>{@name}</CityName>
      </xsl:template>
    
      <xsl:template match="city[@name = 'Venezia']">
        <myCity>
          <xsl:next-match/>
        </myCity>
      </xsl:template>
      
      <xsl:mode on-no-match="shallow-copy" on-multiple-match="use-last"/>
    
    </xsl:stylesheet>
    

    xsl:next-match 在XSLT2.0中也可用,但您需要在模板上指定优先级,而不是依赖 xsl:mode on-multiple-match="use-last" XSLT3中的文本值模板只是语法糖,可以用 xsl:value-of 。

        3
  •  -1
  •   Mustafa J    3 年前

    避免在XSLT中重复创建CityName元素的代码的一种方法是使用命名模板。命名模板是一段可重用的XSLT代码,可以从样式表中的多个位置调用。在您的情况下,您可以创建一个命名模板来创建CityName元素,并从xsl:choot语句的xsl:when和xsl:otherwise子句调用它。以下是如何做到这一点的示例:

    <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="createCityName">
                            <xsl:with-param name="cityName" select="@name" />
                        </xsl:call-template>
                    </myCity>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="createCityName">
                        <xsl:with-param name="cityName" select="@name" />
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        
        <xsl:template name="createCityName">
            <xsl:param name="cityName" />
            <CityName>
                <xsl:value-of select="$cityName" />
            </CityName>
        </xsl:template>
        
        <!-- Identity Transform-->
        <xsl:template match="node()">
            <xsl:copy>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="@*"/>
    </xsl:stylesheet>
    

    在本例中,createCityName模板采用参数cityName,并使用给定的城市名称创建cityName元素。该模板使用xsl:call-template指令从xsl:when和xsl:otherwise子句调用,city元素的@name属性作为cityName参数传递。这样,创建CityName元素的代码在命名模板中只定义一次,并且可以从样式表中的多个位置轻松调用。