首页 > 解决方案 > 使用 XSLT 替换保留 XML 结构的节点中的值

问题描述

我有一个需求,我需要将基于属性的节点的值替换为不同的值,同时保留原始 XML 结构。基本上,当在原始 XML 中遇到特定属性时,我只需要通过替换某些值来复制整个 XML。

以下是转换前和转换后的示例 XML。

原始 XML:

<root>
    <body>
        <node_level1>
            <node_level2>
                <node_level3>
                    <value animal="cat">Munchkin</value>
                </node_level3>
                <node_level3>
                    <value animal="cat">Turkish Angora</value>
                </node_level3>
                <node_level3>
                    <value animal="cat">La Perm</value>
                </node_level3>
            </node_level2>
            <node_level2>
                <node_level3>
                    <node_level4>
                        <value animal="dog">Siberian Husky</value>
                    </node_level4>
                    <node_level4>
                        <value animal="dog">Pug</value>
                    </node_level4>
                    <node_level4>
                        <value animal="dog">Beagle</value>
                    </node_level4>
                </node_level3>
            </node_level2>
        </node_level1>
    </body>
</root>

使用 XSLT 转换数据后,我需要如下 XML:

<root>
    <body>
        <node_level1>
            <node_level2>
                <node_level3>
                    <value animal="cat">Cat Family</value>
                </node_level3>
                <node_level3>
                    <value animal="cat">Cat Family</value>
                </node_level3>
                <node_level3>
                    <value animal="cat">Cat Family</value>
                </node_level3>
            </node_level2>
            <node_level2>
                <node_level3>
                    <node_level4>
                        <value animal="dog">Dog Family</value>
                    </node_level4>
                    <node_level4>
                        <value animal="dog">Dog Family</value>
                    </node_level4>
                    <node_level4>
                        <value animal="dog">Dog Family</value>
                    </node_level4>
                </node_level3>
            </node_level2>
        </node_level1>
    </body>
</root>

这是适用于指定属性的代码,我需要对其进行概括。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl" version="2.0">
    <xsl:template match="/">
        <root>
            <xsl:for-each select="//*[value[@animal = 'cat']]">
                <xsl:copy>
                    <xsl:value-of select="@*"/>
                    <xsl:value-of select="'Cat Family'"/>
                </xsl:copy>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

标签: xmlxsltxslt-2.0xslt-3.0

解决方案


这是一个非常简单的任务,您需要使用身份模板原样复制所有 xml 节点:

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

然后您可以根据您的要求使用单独的value元素模板:

<xsl:template match="value">
    <xsl:choose>
        <xsl:when test="@animal = 'cat'">
            <value animal="cat">Cat Family</value>
        </xsl:when>
        <xsl:when test="@animal = 'dog'">
            <value animal="dog">Dog Family</value>
        </xsl:when>
    </xsl:choose>
</xsl:template>

最终的 XSL 文件是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl" version="2.0">

    <!-- indent elements to see properly -->
    <xsl:output indent="yes"/>

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

    <xsl:template match="value">
        <xsl:choose>
            <xsl:when test="@animal = 'cat'">
                <value animal="cat">Cat Family</value>
            </xsl:when>
            <xsl:when test="@animal = 'dog'">
                <value animal="dog">Dog Family</value>
            </xsl:when>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

推荐阅读