如何在不明确写入的情况下以特定顺序编写元素属性?
考虑:
<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>
在这种情况下可以做些什么?
答案 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>