2012-04-21 61 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