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

Xslt 按输出的特定顺序对属性排序,xslt,attributes,Xslt,Attributes,如何在不显式写入元素属性的情况下按特定顺序写入元素属性 考虑: <xsl:template match="Element/@1|@2|@3|@4"> <xsl:if test="string(.)"> <span> <xsl:value-of select="."/><br/> </span> </xsl:if> </xsl:templ

如何在不显式写入元素属性的情况下按特定顺序写入元素属性

考虑:

<xsl:template match="Element/@1|@2|@3|@4">
    <xsl:if test="string(.)">
        <span>
            <xsl:value-of select="."/><br/>
        </span>
    </xsl:if>
</xsl:template>
理想情况下,我不想测试每个属性是否有值。我想知道我是否可以设定我的展示顺序?或者我需要显式地执行此操作并重复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>



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

我会对属性的本地名称使用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>



不生成依赖于属性顺序的XML。这是非常脆弱的,至少我会认为它是坏的风格。XML不是这样设计的<代码>和
是明确等效的

如果您想要有序输出,请对输出进行排序(而不是依赖有序输入)

此外,
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中名称实际上不能以数字开头。

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

顺序不是在模板的匹配模式中确定的,而是在执行xsl:apply-templates时确定的。因此(使用XSLT2.0),您可以简单地按照所需的顺序编写属性序列,例如,
将按照该顺序处理属性

XSLT1.0没有序列,只有节点集。要产生相同的结果,请按要求的顺序使用
xsl:apply templates
,例如:

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

线索是马丁·霍宁的答案

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

将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>

诺佩纳·诺弗勒

感谢各位的回复。我不是很清楚。我实际上不需要按属性名称对属性进行排序,而是自己指定一个顺序。假设一个文档需要按顺序1、2、3、4显示它们。另一个按顺序2,3。另一个假设是3,1,2,4。我想知道我是否能以某种方式存储属性名的特定序列。。然后,只需对它们进行迭代。基本上,在显示一系列属性值时,要有简洁且非常灵活的内容。希望这有意义?
<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>