XSLT - 在分组中动态添加属性

XSLT - adding attribute dynamically in grouping

我有一个 xml 如下,

<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> 节点的属性值?

以下样式表:

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>

将return:

结果

<?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"可能会更复杂。这将有助于了解所有可能出现的组合。如果一直是"paraN"的格式,那么可以使用:

<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>