2016-11-23 36 views
4

鑑於下面的XML文檔一致過程分組同級元素

<root> 
    <a pos="0" total="2"/> 
    <a pos="1" total="2"/> 

    <a pos="0" total="3"/> 
    <a pos="1" total="3"/> 
    <a pos="2" total="3"/> 

    <a pos="0" total="4"/> 
    <a pos="1" total="4"/> 
    <a pos="2" total="4"/> 
    <a pos="3" total="4"/> 
</root> 

我需要使用XSLT樣式表1.0將其翻譯爲

<root> 
    <group> 
    <a pos="0" total="2"/> 
    <a pos="1" total="2"/> 
    </group> 
    <group> 
    <a pos="0" total="3"/> 
    <a pos="1" total="3"/> 
    <a pos="2" total="3"/> 
    </group> 
    <group> 
    <a pos="0" total="4"/> 
    <a pos="1" total="4"/> 
    <a pos="2" total="4"/> 
    <a pos="3" total="4"/> 
    </group> 
</root> 

即,與0文檔 在@pos屬性各<a>元件隱式啓動由它的一個基團和@total -1以下<a>元件。換言之,爲了說明這一點,@pos表示@total個相鄰元素組中元素的基於0的索引(位置)。

我想出了下面的樣式表,它的工作原理:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="root" /> 
    </xsl:template> 

    <xsl:template match="root"> 
     <xsl:apply-templates select="a[@pos=0]" mode="leader"/> 
    </xsl:template> 

    <xsl:template match="a" mode="leader"> 
     <group> 
      <xsl:apply-templates select="." /> 
      <xsl:apply-templates select="following-sibling::a[position() &lt;= current()/@total - 1]" /> 
     </group> 
    </xsl:template> 

    <xsl:template match="a"> 
     <xsl:copy-of select="." /> 
    </xsl:template> 

</xsl:stylesheet> 

我有我的解決方案的問題是,它使那些a[@pos=0]元素「特殊」:進一步處理每個<a>元素的前瞻性組,我必須首先分別將適當的模板應用到「組長」元素,然後再應用到組中的其他元素。

換句話說,我很希望有像(不正確)

<xsl:template match="a" mode="leader"> 
     <group> 
      <xsl:apply-templates select=". and following-sibling::a[position() &lt;= current()/@total - 1]" /> 
     </group> 
    </xsl:template> 

將適用我<xsl:template match="a">模板的所有元素的組中一氣呵成。 (要改寫我在select表達式中拼寫的內容:「選擇上下文元素及其後續的匹配元素」)。

有沒有辦法讓XSLT 1.0擁有我想要的而不訴諸於像變量和exslt:node-set()黑客?可能有更好的方法來根據元素計數進行這種分組,而這種分組計數比我自己提出的分組計數(這固然使得每個分組中的第一個元素特殊)?


我承認這個問題的標題是相當弱的,但我沒能拿出一個succint其中一個正確反映我問題的essense。

回答

1

你可以這樣做:

<xsl:apply-templates select=". | following-sibling::a[position() &lt;= current()/@total - 1]" /> 

附:使用變量或node-set()函數不符合「破解」的條件。

+0

非常感謝你 - 愚蠢的我;-) 關於你的評論:我試圖盡我所能寫入我的樣式表作爲功能的方法(不知何故吸收了這個被認爲是「最佳實踐」)。根據我的經驗,使用變量或調用'node-set()'(不在XSLT 1.0核心中)幾乎總是表明一些可能在「普通」XSLT工具中被重寫的工作方式。所以是的,你是對的,據說我只是選錯字,試圖說出我的意思。 – kostix

+1

我不同意你對'node-set()'的評估。這對於XSLT 1.0規範的近視是一種解決方法。在許多情況下,避免它會導致一個可怕的裝置。它得到如此廣泛的支持有一個很好的理由。當然,變量是語言的內在和必要部分。 –