在 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-group
和 group-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 节点的文本值,而不是节点本身)
显然,我对 XSLT 2 中分组的工作原理的理解还不够好。我确定使用 xsl:for-each-group
和 group-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 节点的文本值,而不是节点本身)