开发者

Using XPath to compare two XML objects for exact equality

开发者 https://www.devze.com 2023-03-31 02:02 出处:网络
When I have two XML objects, how can I compare them for exact equality (all the same nodes and attributes and values) usin开发者_高级运维g XPath?In XPath 2.0 use the standard function deep-equal().

When I have two XML objects, how can I compare them for exact equality (all the same nodes and attributes and values) usin开发者_高级运维g XPath?


In XPath 2.0 use the standard function deep-equal().

Xpath 1.0 doesn't have such a function, therefore the comparison needs to be performed within the language hosting XPath.

You can use this solution in case you must use XPath 1.0: Generate/get xpath from XML node java to get a collection of XPath expressions for every node of Document1 and another collection of XPath expressions for every node of Document2. Then compare the two collections -- they should have the same number of expressions each and the expressions must be equivalent.

Alternatively, you can generate just verify that the two collections contain the same number of expressions and apply each of the expressions for Document1 on Document2.


XPath 2.0 has a function deep-equal for that: http://www.w3.org/TR/xpath-functions/#func-deep-equal. XPath 1.0 has nothing comparable, you would need to roll your own, in whatever host language you use XPath 1.0 with.


I've used a combination of XSLT 1.0 and Bash to compare specific nodes with each other based on their md5sums.

Using the test="$index=$navigator", because I couldn't copy-of based on a node[$navigator] directly.

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:ns="http://www.example.org">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:param name="navigator"/>
    <xsl:param name="part"/>

    <xsl:template match="/">
    <xsl:for-each select="/ns:mappings/ns:mapping">
        <xsl:variable name="index" select="position()" />
        <xsl:if test="$index=$navigator">
            <xsl:choose>
                <xsl:when test="$part='source'">
                    <xsl:copy-of select="ns:source/ns:taxonpath"/>
                </xsl:when>
                <xsl:when test="$part='target'">
                    <xsl:copy-of select="ns:target/ns:taxonpath"/>
                </xsl:when>
                <xsl:when test="$part='mapping'">
                    <xsl:copy-of select="."/>
                </xsl:when>
            </xsl:choose>
        </xsl:if>
    </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
mappingcount=$(cat mapping.xml | grep "<mapping>" | wc -l)
counter=1

while [  $counter -lt $mappingcount ]; do
    sourcehash=$(xsltproc --stringparam navigator $counter --stringparam part source compare.xslt mapping.xml | md5sum | cut -d " " -f1)
    targethash=$(xsltproc --stringparam navigator $counter --stringparam part target compare.xslt mapping.xml | md5sum | cut -d " " -f1)

    if [ "$sourcehash" == "$targethash" ]; then
        xsltproc --stringparam navigator $counter --stringparam part mapping compare.xslt mapping.xml
    fi
    let counter=counter+1
done

And a part of the mapping.xml

<mappings xmlns="http://www.example.org">
  <mapping>
    <source>
      <taxonpath>
        <taxon>
          <id>c001f86a-4f8f-4420-bd78-381c615ecedc</id>
          <entry>Aardrijkskunde</entry>
        </taxon>
        <taxon>
          <id>65c33fa0-420a-4399-a6f8-595294179df3</id>
          <entry>Weer en klimaat</entry>
        </taxon>
      </taxonpath>
    </source>
    <relationship>ter info</relationship>
    <target>
      <taxonpath>
        <taxon>
          <id>c001f86a-4f8f-4420-bd78-381c615ecedc</id>
          <entry>Aardrijkskunde</entry>
        </taxon>
        <taxon>
          <id>65c33fa0-420a-4399-a6f8-595294179df3</id>
          <entry>Systeem aarde</entry>
        </taxon>
      </taxonpath>
    </target>
  </mapping>
</mappings>
0

精彩评论

暂无评论...
验证码 换一张
取 消