2015-09-18 87 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元素中的序列构造函数按照处理顺序对每个组计算一次......在序列构造函数中,上下文项是相关的初始项组......“ –