2012-04-04 63 views
3

我嘗試檢索一個元素的子元素的屬性值列表,但我希望這些值只出現一次。在XSLT中選擇與每個元素相關的斷點

舉例來說,我有以下XML

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
       <nom-article> 
        <nom-item><data att="1.1"/></nom-item> 
        <nom-item><data att="1.2"/></nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article><data att="2.1"/></nom-article> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

而且我想這樣的結果:

<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
      <nom-article> 
       <att>1.1</att> 
       <att>1.2</att> 
       <nom-item><att>1.1</att></nom-item> 
       <nom-item><att>1.2</att></nom-item> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

我試圖使用xsl:關鍵元素,但它只返回一個元素的值。在這個例子中,第一個標題只返回1.1,而不是第二個。我使用了xsl:

<xsl:key name="allAtt" 
    match="//*[starts-with(name(.),'nom-')]/data" 
    use="@att"/> 
<xsl:template match="nom-title|nom-chapter|nom-article|nom-item"> 
    <xsl:element name="name(.)"> 
     <xsl:apply-templates select=".//*[starts-with(name(.),'nom-')]/data 
    </xsl:element> 
</xsl:template>   
<xsl:template match="data"> 
     <xsl:variable name="att" select="@att"/> 
     <xsl:if test="generate-id(.)=generate-id(key('allAtt',$att)[1]"> 
      <xsl:element name="att"><xsl:value-of select="$att"></xsl:element> 
     </xsl:if> 
</xsl:template> 
+2

根據我的經驗,xslt需要有效的xml開始。它看起來像「nom-article」元素沒有關閉。可能想嘗試首先解決這個問題。 – 2012-04-04 10:46:54

+1

我同意Justin的觀點,請首先向我們展示一個格式良好的XML輸入樣本,目前輸入的結構並不清晰,有幾個標籤沒有正確關閉(例如'',' ')。 – 2012-04-04 10:53:09

+0

對不起,錯誤的複製粘貼,我已修復它。 – claudex 2012-04-04 11:06:23

回答

2

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kData-nom-article" match="data" use= 
"concat(generate-id(ancestor::nom-article[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-chapter" match="data" use= 
"concat(generate-id(ancestor::nom-chapter[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-title" match="data" use= 
"concat(generate-id(ancestor::nom-title[1]), 
     '+', @att)"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

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

<xsl:template match="nom-title|nom-article|nom-chapter"> 
    <xsl:copy> 
    <xsl:apply-templates mode="list" select= 
    ".//data[generate-id() 
      = 
       generate-id(key(concat('kData-', name(current())), 
           concat(generate-id(current()), 
            '+', @att 
            ) 
          ) 
           [1] 
         ) 
      ]"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="data" mode="list"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="non-item/data"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="*[not(self::nom-item)]/data"/> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
       <nom-article> 
        <nom-item> 
         <data att="1.1"/> 
        </nom-item> 
        <nom-item> 
         <data att="1.2"/> 
        </nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article> 
        <data att="2.1"/> 
       </nom-article> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

產生想要的,正確的結果:

要執行的表達三種不同Muenchian分組爲一體,通過動態構建用於實際分組的項的名稱:
<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <att>1.2</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-item> 
       <data att="1.1"/> 
      </nom-item> 
      <nom-item> 
       <data att="1.2"/> 
      </nom-item> 
     </nom-article> 
     </nom-chapter> 
     <nom-chapter> 
     <att>2.1</att> 
     <att>1.1</att> 
     <nom-article> 
      <att>2.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

說明

記住:關鍵名是一個字符串並在必要時(如在這種情況下),該名稱可以被動態構造,或者作爲參數傳遞。