简体   繁体   English

用xslt比较两个xml文件?

[英]compare two xml files with xslt?

I have 2 xml files.我有 2 个 xml 文件。 How can I compare both files are equal or not by using xslt?如何使用 xslt 比较两个文件是否相等? If not equal means where the changes havebeen occur in the second xml?如果不相等意味着在第二个 xml 中发生了哪些变化?

In XPath 2.0 you could simple use fn:deep-equal .在 XPath 2.0 中,您可以简单地使用fn:deep-equal

Following the same pattern in XSLT 1.0, this stylesheet:遵循 XSLT 1.0 中的相同模式,此样式表:

<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

This is the stylesheet I wrote to compare two XML files with different order in nodes and attributes.这是我编写的样式表,用于比较两个节点和属性顺序不同的 XML 文件。 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.使用任何文本比较工具找出差异或增强 XSLT 以执行您想要的操作。

<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>

XSLT is best used for transforming one XML dialect to another. XSLT 最适合用于一种 XML 方言转换为另一种方言。

To compare XML files, I would use an XML parser on your platform and compare the documents using it.为了比较 XML 文件,我会在您的平台上使用 XML 解析器并使用它比较文档。

It is possible to compare the two, but I would advise against it, if you have other options.可以将两者进行比较,但如果您有其他选择,我建议您不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM