如何使用XSLT使用相关元素组重新格式化XML

我正在改进一些我通过使用XSLT进行清理而继承的
XML,但我正在努力解决一个问题.看起来像这样:

    <rules>
        <if condition="equals" arg1="somevar" arg2="1"/>
        <elseif condition="equals" arg1="somevar" arg2="2"/>
        <elseif condition="equals" arg1="somevar" arg2="3"/>
        <else/>
        <if condition="equals" arg1="somevar" arg2="4"/>
        <else/>
    </rules>

这看起来很难用XSD验证,所以我想把它变成这样的东西 – 想法?

    <rules>
        <conditionSet>
            <if condition="equals" arg1="somevar" arg2="1"/>
            <elseif condition="equals" arg1="somevar" arg2="2"/>
            <elseif condition="equals" arg1="somevar" arg2="3"/>
            <else/>
        </conditionSet>
        <conditionSet>
            <if condition="equals" arg1="somevar" arg2="4"/>
            <else/>
        </conditionSet>
    </rules>

最佳答案 将elseif和else元素按其前面的if元素分组:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:key name="block" match="elseif|else" 
             use="generate-id(preceding-sibling::if[1])"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="rules">
        <xsl:copy>
            <xsl:apply-templates select="@*|
                    node()[not(self::elseif or self::else)]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="if">
        <conditionSet>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
            <xsl:apply-templates select="key('block', generate-id())"/>
        </conditionSet>
    </xsl:template>
</xsl:stylesheet>

此样式表生成请求的输出.

说明:xsl:key将每个if元素与其后面的相关元素相关联,以便稍后当我们匹配if时,我们可以简单地包装并复制整个集合.

点赞