在 XSLT 2 中使用 for-each-group 和 group-adjacent 进行分组和包装

Using for-each-group with group-adjacent for grouping and wrapping in XSLT 2

显然,我对 XSLT 2 中分组的工作原理的理解还不够好。我确定使用 xsl:for-each-groupgroup-adjacent 作为属性的方法是正确的。但是,我没有得到想要的结果。

我想将 XML 源中的几个相邻元素分组。这些元素通过后代元素的属性值来标识。我需要用一个新元素来包装它们(例如 p div="lernz")。有时这些元素显示为邻居,有时不是。

我的样式表没有得到正确的结果。有时候会匹配到我认为应该是组的第一项之前的元素。但到目前为止,在我的结果中,我认为是一组的每一项都被包装了。错误在哪里?非常感谢任何帮助。

XML 输入

 <wx:sect>
  <w:p>
    <w:pPr w:val = 'Lern'/>
  </w:p>
  <w:p>
    <w:pPr w:val = 'Lern'/>
  </w:p>
  <w:p>
    <w:pPr w:val = 'Merk'/>
  </w:p>
  <w:p>
    <w:pPr w:val = 'Lern'/>
  </w:p>
  <w:p>
    <w:pPr w:val = 'Merk'/>
  </w:p>
</w:sect>

期望的输出

<wx:sect>
   <p div="wrapper-lernz">
       <w:p>
          <w:pPr w:val = 'Lern'/>
        </w:p>
        <w:p>
          <w:pPr w:val = 'Lern'/>
        </w:p>
    </p>
        <w:p>
          <w:pPr w:val = 'Merk'/>
        </w:p>
    <p div="wrapper-lernz">
      <w:p>
        <w:pPr w:val = 'Lern'/>
      </w:p>
    </p>
      <w:p>
        <w:pPr w:val = 'Merk'/>
      </w:p>
</w:sect>

我的样式表(部分)

<xsl:template match="//w:p[w:pPr[@w:val]]">
    <xsl:for-each-group select="current()" group-adjacent="//@w:val = 'Lern">
         <p div="wrapper-lernz">
             <xsl:value-of select="current-group()"/>
          </p>
        </xsl:for-each-group>
    </xsl:template>

您的模板与 w:p 相匹配,但如果您想要对相邻元素进行分组,则应与父 w:sect 标记相匹配。通过执行 xsl:for-each-group select="current()",您正在尝试对单个元素进行分组。

要处理仅将 "lern" 元素放入容器标签中,您应该在 "w:val" 值上设置 group-adjacent=,然后使用 xsl:choose 来决定是否添加父标签。

试试这个模板:

<xsl:template match="//w:sect[w:p[w:pPr/@w:val]]">
  <xsl:copy>
    <xsl:for-each-group select="w:p" group-adjacent="w:pPr/@w:val">
      <xsl:choose>
        <xsl:when test="current-grouping-key() = 'Lern'">
          <p div="wrapper-lernz">
             <xsl:copy-of select="current-group()"/>
          </p>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="current-group()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

(注意它也 xsl:copy-of 而不是 xsl:value-of 因为 xsl:value-of 只是 returns 节点的文本值,而不是节点本身)