首页 > 解决方案 > 用 XSLT 中的元素包围匹配的兄弟姐妹

问题描述

如何在 XSLT 中用新元素包围匹配的相邻兄弟?

在这个例子中,要包围的元素是那些匹配的bar[@baz='quux']

XML 输入:

<foo>
    <bar>X1</bar>
    <bar baz="quux">X2</bar>
    <bar baz="quux">X3</bar>
    <xnorfzt>X4</xnorfzt>
    <bar baz="quux">X5</bar>
</foo>

预期的 XML 输出:

<foo>
    <bar>X1</bar>
    <new>
        <bar baz="quux">X2</bar>
        <bar baz="quux">X3</bar>
    </new>
    <xnorfzt>X4</xnorfzt>
    <new>
        <bar baz="quux">X5</bar>
    </new>
</foo>

标签: xmlxslt

解决方案


在 XSLT 2.0 中试试这个

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="foo">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="@baz='quux'">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <new>
                        <xsl:apply-templates select="current-group()"/>
                    </new>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                    
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

请参阅https://xsltfiddle.liberty-development.net/pNvt6XR上的转换

在 XSLT 1.0 中

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="bar[preceding-sibling::*[1][self::bar][@baz = 'quux']]" priority="1"/>

<xsl:template match="bar[@baz = 'quux']">
    <new>
        <xsl:call-template name="wrapbar">
            <xsl:with-param name="node" select="."/>
        </xsl:call-template>
    </new>
</xsl:template>

<xsl:template name="wrapbar">
    <xsl:param name="node"/>
    <xsl:copy-of select="$node"/>
    <xsl:if test="$node/following-sibling::*[1][self::bar][@baz = 'quux']">
        <xsl:call-template name="wrapbar">
            <xsl:with-param name="node" select="$node/following-sibling::*[1]"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

请参阅https://xsltfiddle.liberty-development.net/pNvt6XR/1上的转换


推荐阅读