XSLT根据差异合并节点

时间:2015-04-03 06:09:00

标签: xml xslt xslt-1.0

输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <book name="akhil" root="indian" default_attribute="10">
        <type default_attribute="20">novel</type>
        <price>200</price>      
    </book>
    <book name="indian" default_attribute="0">
        <type default_attribute="0">novel</type>
        <price default_attribute="0">100</price>
        <category default_attribute="0">thriller</category>
    </book>
</root>

必需的输出:

<root>
    <book name="akhil" default_attribute="10">
        <type default_attribute="20">novel</type>
        <price default_attribute="0">200</price>
        <category default_attribute="0">thriller</category>
    </book> 
</root>

使用XSLT 1.0我们如何产生这个输出? 任何帮助表示赞赏。

合并应该以这样的方式进行:如果有root属性,则获取具有root属性值的书名,然后将原始书(具有root属性)与没有root属性的书合并

如果不存在具有给定根属性值的书名,则只需输出当前书籍节点

1 个答案:

答案 0 :(得分:0)

我会使用XSLT中的键来引用book元素及其属性。它可能无法满足您的需求,但我希望能够根据需要对您的问题进行一些修改来帮助您解决问题:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="book-by-name" match="book" use="@name"/>
    <xsl:key name="book-by-root" match="book" use="@root"/>

    <!-- Identity transform template to copy nodes and attributes -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- template to merge book with @name with match @root's book -->
    <xsl:template match="book[@root]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="key('book-by-name', @root)/*"/>
        </xsl:copy>
    </xsl:template>

    <!-- template to merge @price with value from book[@root]/price -->
    <xsl:template match="book[not(@root) and count(key('book-by-root', @name)) > 0]/price">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:value-of select="key('book-by-root', ../@name)/price"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="book/@root"/>

    <xsl:template match="book[not(@root) and count(key('book-by-root', @name)) > 0]"/>

</xsl:stylesheet>