问题
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?
回答1:
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
回答2:
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.
回答3:
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>
</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>
来源:https://stackoverflow.com/questions/4546190/compare-two-xml-files-with-xslt