按输出的特定顺序对属性排序

时间:2010-02-18 10:31:24

标签: xslt attributes

如何在不明确写入的情况下以特定顺序编写元素属性?

考虑:

<xsl:template match="Element/@1|@2|@3|@4">
    <xsl:if test="string(.)">
        <span>
            <xsl:value-of select="."/><br/>
        </span>
    </xsl:if>
</xsl:template>

属性应按1, 2, 3, 4的顺序显示。遗憾的是,您不能保证XML中属性的顺序,它可以是<Element 2="2" 4="4" 3="3" 1="1">

因此上面的模板将产生以下内容:

<span>2</span>
<span>4</span>
<span>3</span>
<span>1</span>

理想情况下,如果每个属性都有值,我不想测试它们。我想知道我是否能以某种方式设置显示器的顺序?或者我是否需要明确地执行此操作并重复if测试,如下所示:

<xsl:template match="Element">

    <xsl:if test="string(./@1)>
        <span>
            <xsl:value-of select="./@1"/><br/>
        </span>
    </xsl:if>
    ...
    <xsl:if test="string(./@4)>
        <span>
            <xsl:value-of select="./@4"/><br/>
        </span>
    </xsl:if>
</xsl:template>

在这种情况下可以做些什么?

4 个答案:

答案 0 :(得分:6)

在之前的一个问题中,您似乎使用了XSLT 2.0,所以我希望这次也可以使用XSLT 2.0解决方案。

订单不是在模板的匹配模式中确定的,而是在您执行xsl:apply-templates时确定。所以(使用XSLT 2.0)你可以按照你想要的顺序编写一系列属性,例如: <xsl:apply-templates select="@att2, @att1, @att3"/>将按此顺序处理属性。

XSLT 1.0没有序列,只有节点集。要生成相同的结果,请按所需顺序使用xsl:apply-templates,例如:

<xsl:apply-templates select="@att2"/>
<xsl:apply-templates select="@att1"/>
<xsl:apply-templates select="@att3"/>

答案 1 :(得分:3)

不要生成依赖于属性顺序的XML。这是非常脆弱的,至少可以说,我认为它的风格很糟糕。 XML不是以这种方式设计的; <elem a="1" b="2" /><elem a="1" b="2" />明确相同。

如果您想要有序输出,请订购输出(而不是依赖有序输入)。

此外,match="Element/@1|@2|@3|@4"不等同于match="Element/@1|Element/@2|Element/@3|Element/@4",但我相信你的意思是后者。

话虽如此,你可以这样做:

<xsl:template match="Element/@1|Element/@2|Element/@3|Element/@4">
  <xsl:if test="string(.)">
    <span>
      <xsl:value-of select="."/><br/>
    </span>
  </xsl:if>
</xsl:template>

<xsl:template match="Element">
  <xsl:apply-templates select="@1|@2|@3|@4">
    <!-- order your output... -->
    <xsl:sort select="name()" />
  </xsl:apply-templates>
</xsl:template>

编辑:我会将其视为@1等只是示例,因为名称实际上不能以XML中的数字开头。

答案 2 :(得分:1)

我在属性的local-name上使用xsl:sort来获得你想要的结果。我也会使用不同的模式,因此不会在其他地方意外调用结果。

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="Element">
      <xsl:apply-templates select="@*" mode="sorted">
        <xsl:sort select="local-name()" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Element/@a|@b|@c|@d" mode="sorted">
    <xsl:if test="string(.)">
        <span>
            <xsl:value-of select="."/><br/>
        </span>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

答案 3 :(得分:0)

线索是 Martin Honnen 的答案

复制属性并有条件地将新属性添加到属性列表的末尾。

将 rel="noopener noreferrer" 添加到所有外部链接。

<xsl:template match="a">
  <xsl:copy>
  <xsl:if test="starts-with(./@href,'http')">
    <xsl:apply-templates select="./@*"/>
    <!-- Insert rel as last node -->
    <xsl:attribute name="rel">noopener noreferrer</xsl:attribute>
  </xsl:if>
      <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
</xsl:template>

<xsl:template match="a/@href|a/@target|a/@rel">
    <!--
    Allowed attribute on anchor
    -->
    <xsl:attribute name="{name()}">
      <xsl:value-of select="."></xsl:value-of>
    </xsl:attribute>
  </xsl:template>

您还可以通过调用应用模板来指定属性序列,并按照您想要的顺序进行每个选择。

<xsl:template match="a">
  <xsl:copy>
  <xsl:if test="starts-with(./@href,'http')">
    <xsl:apply-templates select="./@id"/>
    <xsl:apply-templates select="./@href"/>
    <xsl:apply-templates select="./@target"/>
    <!-- Insert rel as last node -->
    <xsl:attribute name="rel">noopener noreferrer</xsl:attribute>
  </xsl:if>
      <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
</xsl:template>