我有2个xml文件。如何使用xslt比较两个文件是否相等?如果不相等意味着在第二个xml中发生了哪些变化?
答案 0 :(得分:4)
在XPath 2.0中,您可以简单地使用fn:deep-equal
。
在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>
输出:
Documents are different
答案 1 :(得分:0)
XSLT最适合将一种XML方言转换为另一种XML方言。
为了比较XML文件,我将在您的平台上使用XML解析器并使用它来比较文档。
可能比较两者,但如果您有其他选择,我会建议您反对。
答案 2 :(得分:0)
这是我编写的样式表,用于比较节点和属性中具有不同顺序的两个XML文件。它将生成两个文本文件,其中包含所有叶节点路径的有序列表。使用任何文本比较工具来发现差异或增强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>
</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>