2012-04-21 70 views
2

我需要按特定顺序处理属性(具有它们的任何节点)的属性。例如:XSL按订单处理属性

<test> 
    <event 
     era ="modern" 
     year ="1996" 
     quarter = "first" 
     day = "13" 
     month= "January" 
     bcad ="ad" 
     hour ="18" 
     minute = "23" 
     >The big game began.</event> 
    <happening 
     era ="modern" 
     day = "18" 
     bcad ="ad" 
     month= "February" 
     hour ="19" 
     minute = "24" 
     >The big game ended.</happening> 
    <other>Before time existed.</other> 
</test> 

这是我需要他们

<xsl:template match="test//*"> 
    <div> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

将格式化的东西。也就是说,我会得到

<div><span class="era">modern</span> 
    <span class="year">1996</span> 
    <span class="quarter">first</span> 
    <span class="day">13</span> 
    <span class="month">January</span> 
    <span class="bcad">ad</span> 
    <span class="hour">18</span> 
    <span class="minute">23</span>The big game began.</div> 
<div><span class="era">modern</span> 
    <span class="day">18</span> 
    <span class="bcad">ad</span> 
    <span class="month">February</span> 
    <span class="hour">19</span> 
    <span class="minute">24</span>The big game ended.</div> 
<div>Before time existed.</div> 

(虽然没有添加新行,我在这里添加了易读性)。

但是属性的顺序不一定是正确的。

为了解决这个问题,我可以改变<xsl:apply-templates select="@*" /><xsl:call-template name="atts" />并补充说,需要的顺序应用模板的模板,像这样:

<xsl:template match="test//*"> 
    <div> 
     <xsl:call-template name="atts" /> 
     <xsl:apply-templates /> 
    </div> 
</xsl:template> 

<xsl:template name="atts"> 
    <xsl:apply-templates select="@era" /> 
    <xsl:apply-templates select="@bcad" /> 
    <xsl:apply-templates select="@year" /> 
    <xsl:apply-templates select="@quarter" /> 
    <xsl:apply-templates select="@month" /> 
    <xsl:apply-templates select="@day" /> 
    <xsl:apply-templates select="@hour" /> 
    <xsl:apply-templates select="@minute" />   
</xsl:template> 

<xsl:template match="@*"> 
    <span class="{name()}"> 
     <xsl:value-of select="."/> 
    </span> 
</xsl:template> 

这是最好的实践方式来处理特定的顺序属性?我一直在想,如果有一种方法使用键或全局变量。

我需要使用XSLT 1.0,在真实情况下,有几十个属性,而不仅仅是八个。

回答

1

与元素相比,例如,XML中的属性顺序不重要,即XPath和XSLT可以按任意顺序处理它们。因此,强制给定订单的唯一方法是以某种方式指定它。一种方法是像上一个代码示例那样显式调用它们。您还可以提取所有属性名称并将它们存储在单独的XML文件中,例如像

<attributes> 
    <attribute>era</attribute> 
    <attribute>year</attribute> 
    <attribute>month</attribute> 
    ... 
<attributes> 

现在你可以加载这些元素与文档()函数,并遍历所有属性元素:

<xsl:variable name="attributes" select="document('attributes.xml')//attribute"/> 
... 
<xsl:template match="*"> 
    <xsl:variable name="self" select="."/> 
    <xsl:for-each select="$attributes"> 
    <xsl:apply-templates select="$self/@*[name()=current()]"/> 
    </xsl:for-each>  
</xsl:template> 
+0

除了没有必要建立一个属性列表单独的XML文件 - 它可以而且很可能应该直接进入XSLT文件本身(然后使用不带参数的document()函数进行引用。 – 2012-04-23 02:26:09

+0

是的,没错,但是我不会手动提取属性,但是编写一个样式表,从给定的XML文件中提取它们。对我来说,这更容易o在一个单独的文件中维护这样一个列表,而不是在每次提取和重新排序属性时将所有内容都复制到样式表中。但这可能只是个人偏好。 – Martin 2012-04-23 06:24:33

+0

@Martin你看到我可以在每个属性之间添加分隔符吗?假设apply-template刚刚返回值,属性是月,日和年。我想要“5/16/2012”。用你的方法,我不能测试pos()!= last(),因为这些函数计算for-each中的所有属性,而不仅仅是那些name()= current()的属性。 – JPM 2012-05-17 04:18:04