如何使用 XSLT 将特定块包装在 XML 文档中

我有一个如下所示的 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <p>One</p>
    <p>Two</p>
    <p>Three</p>
    <p type="start" />
    <p>A</p>
    <p><id>1</id>B</p>
    <p type="end" />
    <p>Four</p>
    <p>Five</p>
    <p type="start" />
    <p>C</p>
    <p><id>3</id>D</p>
    <p type="end" />
    <p>Six</p>
</doc>

我需要在 p[@type ='start']p[@type ='end'] 元素之间包装所有内容,同时保留文档的其余部分。因此输出应该是:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <p>One</p>
    <p>Two</p>
    <p>Three</p>
    <group>
        <p>A</p>
        <p><id>1</id>B</p>
    </group>
    <p>Four</p>
    <p>Five</p>
    <group>
        <p>C</p>
        <p><id>3</id>D</p>
    </group>
    <p>Six</p>
</doc>

基于 xslt: select all specific node between two nodes but stop at specific node 我试过:

<xsl:template match="doc">
    <xsl:for-each-group select="*" group-starting-with="p[@type = 'start']">
        <xsl:if test="self::p[@type = 'start']">
        <group>
            <xsl:for-each-group select="current-group()[position() gt 1]" group-ending-with="p[@type = 'end']">
                <xsl:if test="position() eq 1">
            <xsl:apply-templates select="current-group()[not(self::p[@type = 'end'])]" />
                </xsl:if>
            </xsl:for-each-group>
        </group>
        </xsl:if>
    </xsl:for-each-group>
</xsl:template>

不幸的是,这完全消除了不在 p[@type ='start']p[@type ='end'] 元素之间的所有内容。因此,我如何获得相同的结果,但保留文档的其余部分(为其他模板传递)。

ooole 回答:如何使用 XSLT 将特定块包装在 XML 文档中

使用 xsl:choose 而不是 xsl:if 并执行两次,如果开始和结束都找到,也只插入 group 包装器:

<xsl:template match="doc">
  <xsl:copy>
    <xsl:for-each-group select="*" group-starting-with="p[@type = 'start']">
      <xsl:choose>
        <xsl:when test="self::p[@type = 'start']">
            <xsl:for-each-group select="current-group()[position() gt 1]" group-ending-with="p[@type = 'end']">                <xsl:choose>
                    <xsl:when test="current-group()[last()][self::p[@type = 'end']]">
                        <group>
                            <xsl:apply-templates select="current-group()[not(position() = last())]"/>
                        </group>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="current-group()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

这假设您已将身份转换设置为复制节点的基本模板。

本文链接:https://www.f2er.com/428.html

大家都在问