2015-09-18 20 views
0

我有一個xml像如下,XSLT - 在分組

<doc> 
    <section> 
     <p id="main">aa</p> 
     <p id="main">bb</p> 
     <p id="main">cc</p> 
     <p id="para1">dd</p> 
     <p id="main">ee</p> 
     <p id="main">ff</p> 
     <p id="main">gg</p> 
     <p id="para2">hh</p> 
     <p id="main">ii</p> 
     <p id="main">jj</p> 
     <p id="para1">xx</p> 
     <p id="main">yy</p> 
     <p id="main">zz</p> 
    </section> 
</doc> 

我的任務是小組根據id="para1"id='para2'屬性上述內容,並添加一個節到每個組動態添加屬性。我期望的輸出是

<doc> 
    <section> 
     <p id="main">aa</p> 
     <p id="main">bb</p> 
     <p id="main">cc</p> 
    </section> 
    <section type="First para"> 
     <p id="para1">dd</p> 
     <p id="main">ee</p> 
     <p id="main">ff</p> 
     <p id="main">gg</p> 
    </section> 
    <section type="Second para"> 
     <p id="para2">hh</p> 
     <p id="main">ii</p> 
     <p id="main">jj</p> 
    </section> 
    <section type="First para"> 
     <p id="para1">xx</p> 
     <p id="main">yy</p> 
     <p id="main">zz</p> 
    </section> 
</doc> 

的XSL做這個任務如下,

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

    <xsl:template match="section"> 
     <xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]"> 
      <section type="?"> 
       <xsl:apply-templates select="current-group()"/> 
      </section>  
     </xsl:for-each-group> 
    </xsl:template> 

這XSL將做的工作,但你可以建議的方式,我怎麼可以添加加入type屬性值<section>節點基於組?

回答

2

以下樣式表:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

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

<xsl:template match="section"> 
    <xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]"> 
     <section> 
      <xsl:if test="current-group()[1][not(@id='main')]"> 
       <xsl:attribute name="type" select="current-group()[1]/@id"/> 
      </xsl:if> 
      <xsl:apply-templates select="current-group()"/> 
     </section>  
    </xsl:for-each-group> 
</xsl:template> 

</xsl:stylesheet> 

將返回:

結果

<?xml version="1.0" encoding="utf-8"?> 
<doc> 
    <section> 
     <p id="main">aa</p> 
     <p id="main">bb</p> 
     <p id="main">cc</p> 
    </section> 
    <section type="para1"> 
     <p id="para1">dd</p> 
     <p id="main">ee</p> 
     <p id="main">ff</p> 
     <p id="main">gg</p> 
    </section> 
    <section type="para2"> 
     <p id="para2">hh</p> 
     <p id="main">ii</p> 
     <p id="main">jj</p> 
    </section> 
    <section type="para1"> 
     <p id="para1">xx</p> 
     <p id="main">yy</p> 
     <p id="main">zz</p> 
    </section> 
</doc> 

將「para1」和「para2」分別轉換爲「First para」和「Second para」可能會更加複雜。這將有助於瞭解可能出現的所有可能的組合。如果它總是在「巴蘭」的格式,那麼你可以使用:

<xsl:attribute name="type"> 
    <xsl:number value="substring-after(current-group()[1]/@id, 'para')" format="Ww" ordinal="yes"/> 
    <xsl:text> para</xsl:text> 
</xsl:attribute> 

產生:

<?xml version="1.0" encoding="utf-8"?> 
<doc> 
    <section> 
     <p id="main">aa</p> 
     <p id="main">bb</p> 
     <p id="main">cc</p> 
    </section> 
    <section type="First para"> 
     <p id="para1">dd</p> 
     <p id="main">ee</p> 
     <p id="main">ff</p> 
     <p id="main">gg</p> 
    </section> 
    <section type="Second para"> 
     <p id="para2">hh</p> 
     <p id="main">ii</p> 
     <p id="main">jj</p> 
    </section> 
    <section type="First para"> 
     <p id="para1">xx</p> 
     <p id="main">yy</p> 
     <p id="main">zz</p> 
    </section> 
</doc> 
+0

裏面'的for-each-group'上下文節點是在每個第一項如果test =「current-group()[1] [not(@ id ='main')]」>''爲''。 –

+0

@MartinHonnen我相信你是正確的,但我無法在規格中找到確認。它所說的是,*初始項目*是*上下文項目* **,用於排序**。 –

+0

'for-each-group'部分定義爲「對於每個組,羣組中首先按人口順序排列的項目被稱爲組的初始項目。」然後稍後說:「包含在xsl:for-each-group元素中的序列構造函數按照處理順序對每個組計算一次......在序列構造函數中,上下文項是相關的初始項組......「 –