compare two xml files with xslt?

前端 未结 3 787
萌比男神i
萌比男神i 2021-02-10 13:12

I have 2 xml files. How can I compare both files are equal or not by using xslt? If not equal means where the changes havebeen occur in the second xml?

相关标签:
3条回答
  • 2021-02-10 13:41

    XSLT is best used for transforming one XML dialect to another.

    To compare XML files, I would use an XML parser on your platform and compare the documents using it.

    It is possible to compare the two, but I would advise against it, if you have other options.

    0 讨论(0)
  • 2021-02-10 14:02

    This is the stylesheet I wrote to compare two XML files with different order in nodes and attributes. It will generate two text files, containing the ordered list of all the leaf nodes path. Use any text compare tool to spot out the differences or enhance the XSLT to do what you want.

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method="text" indent="no" omit-xml-declaration="yes" name="output" />
    
    <xsl:param name="OTHERFILENAME">xml_file_to_diff.xml</xsl:param>
    <xsl:param name="ORIGINAL_OUTPUT_FILENAME">ORIGINAL.txt</xsl:param>
    <xsl:param name="OTHER_OUTPUT_FILENAME">OTHER.txt</xsl:param>
    
    <xsl:template match="/">
        <xsl:call-template name="convertXMLHierarchyToFullPath">
            <xsl:with-param name="node" select="*"/>
            <xsl:with-param name="filename" select="$ORIGINAL_OUTPUT_FILENAME"/>
        </xsl:call-template>
        <xsl:call-template name="convertXMLHierarchyToFullPath">
            <xsl:with-param name="node" select="document($OTHERFILENAME)/*"/>
            <xsl:with-param name="filename" select="$OTHER_OUTPUT_FILENAME"/>
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="convertXMLHierarchyToFullPath">
        <xsl:param name="node"/>
        <xsl:param name="filename"/>
    
        <xsl:variable name="unorderedFullPath">
            <xsl:apply-templates select="$node"/>
        </xsl:variable>
    
        <xsl:result-document href="{$filename}" format="output">
            <xsl:for-each select="$unorderedFullPath/*">
                <xsl:sort select="@path" data-type="text"/>
                <xsl:value-of select="@path"/>
                <xsl:text>&#xA;</xsl:text>
            </xsl:for-each>
        </xsl:result-document>
    </xsl:template>
    
    <xsl:template match="*">
        <xsl:if test="not(*)">
            <leaf>
                <xsl:attribute name="path">
                    <xsl:for-each select="ancestor-or-self::*">
                        <xsl:value-of select="name()"/>
                        <xsl:for-each select="@*">
                            <xsl:sort select="name()" data-type="text"/>
                            <xsl:text>[</xsl:text>
                            <xsl:value-of select="name()"/>
                            <xsl:text>:</xsl:text>
                            <xsl:value-of select="."/>
                            <xsl:text>]</xsl:text>
                        </xsl:for-each>
                        <xsl:text>/</xsl:text>
                    </xsl:for-each>
                    <xsl:value-of select="."/>
                </xsl:attribute>
            </leaf>
        </xsl:if>
        <xsl:apply-templates select="*"/>
    </xsl:template>
    
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2021-02-10 14:05

    In XPath 2.0 you could simple use fn:deep-equal.

    Following the same pattern in XSLT 1.0, this stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pSource2" select="'emp2.xml'"/>
        <xsl:template match="/*">
            <xsl:variable name="vDeep-equal">
                <xsl:apply-templates select="." mode="deep-equal">
                    <xsl:with-param name="pTarget" select="document($pSource2)/*"/>
                </xsl:apply-templates>
            </xsl:variable>
            <xsl:choose>
                <xsl:when test="normalize-space($vDeep-equal)">
                    <xsl:text>Documents are different</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>Documents are deep equal</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        <xsl:template match="*" mode="deep-equal">
            <xsl:param name="pTarget"/>
            <xsl:choose>
                <xsl:when test="$pTarget/self::* and
                                local-name()=local-name($pTarget) and
                                namespace-uri()=namespace-uri($pTarget) and
                                count(@*)=count($pTarget/@*) and
                                count(*|text()[normalize-space()]) =
                                   count($pTarget/*|
                                         $pTarget/text()[normalize-space()])">
                    <xsl:for-each select="@*">
                        <xsl:if test="$pTarget/@*[name()=name(current())] != .">
                            <xsl:text>false</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                    <xsl:for-each select="*|text()[normalize-space()]">
                        <xsl:variable name="vPosition" select="position()"/>
                        <xsl:apply-templates select="." mode="deep-equal">
                            <xsl:with-param name="pTarget"
                                            select="($pTarget/*|
                                                     $pTarget/text()
                                                        [normalize-space()])
                                                                [$vPosition]"/>
                        </xsl:apply-templates>
                    </xsl:for-each>
                </xsl:when>
                <xsl:otherwise>false</xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        <xsl:template match="text()" mode="deep-equal">
            <xsl:param name="pTarget"/>
            <xsl:if test="not($pTarget/self::text() and
                          string() = string($pTarget))">
                <xsl:text>false</xsl:text>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    Documents are different
    
    0 讨论(0)
提交回复
热议问题