Ignoring Changes in a Comparison

Ignoring Changes in a Comparison

This section describes the concepts behind ignoring changes. For the resources associated with this sample, see the Bitbucket repo here.

The purpose of a comparison is to show all of the changes between two files. However there may be cases where you want to ignore changes from a comparison, such as when the changes are not relevant to you, or if they cause problems in further processing. The XSLT filters have been provided to allow you to ignore selected changes. There is also an in-built ignore changes functionality allows you to ignore changes without using an additional filter.

What Does "Ignore" Really Mean?

Consider this simple example of an attribute change:

Input A: <x y='1'/>
Input B: <x y='2'/>

'Ignore Changes' could mean any of the following:

  • Prefer the 'B' value: <x y='2'/>

  • Prefer the 'A' value: <x y='1'/>

  • Take the 'B' value if it exists; otherwise omit it: <x y='2'/>

  • Take the 'A' value if it exists; otherwise omit it: <x y='1'/>

  • Remove the change completely from the result: <x/>

Document Comparator API Settings

Using the Java API or the DCP

The following API settings can be used to configure the Document Comparator pipeline to ignore changes:

Setting

Description

ignoreChangesConfig

An in-built setting in the Document Comparator to allow you to ignore specified changes

locations

List of location objects with XPaths to elements or attributes to ignore changes on, and the result rules to be used to resolve the ignored locations in the result

resultRule

The rule to resolve ignored locations in the result

ResultRule Options

ResultRule

Description

ResultRule.BA

Default. Copy the B value if it exists, otherwise copy old value.

ResultRule.AB

Copy the A value if it exists, otherwise copy new value.

ResultRule.A

Copy A value if it exists, otherwise don't output.

ResultRule.B

Copy B value if it exists, otherwise don't output.

ResultRule.DELETE

Do not copy under any circumstances. Removes the changes (but still processes the subtree if it exists).

Example 1.1: Java API to mark parts of the document to be ignored (See IgnoreChangesWithAPISettingsSample.java in the sample on Bitbucket)

Java
DocumentComparator dc = new DocumentComparator();
List<Location> locations = new ArrayList<>();
locations.add(new Location("/addressBook/person/name/@id"));
locations.add(new Location("/addressBook/person/log", ResultRule.DELETE));
IgnoreChangesConfig ignoreChangesConfig = new IgnoreChangesConfig(locations);
dc.setIgnoreChangesConfig(ignoreChangesConfig);
dc.compare(input1, input2, new File(outputFileName));

Example 1.2: DCP to mark parts of the document to be ignored (See ignore-changes.dcp in the sample on Bitbucket)

XML
<standardConfig>
  <ignoreChangesConfig>
    <locations>
      <location ignoreXpath="/addressBook/person/name/@id"/>
      <location ignoreXpath="/addressBook/person/log" resultRule="DELETE"/>
    </locations>
  </ignoreChangesConfig>
</standardConfig>

Using Namespaces Whilst Providing XPaths

When providing XPaths using the Java API or the DCP it may be useful to be able to use namespace prefixes to refer to elements within the input documents. For more information on how to define the namespaces to be used please see Using Namespaces Within XPath Expressions.

Example Comparisons

This document discusses how to handle comparisons using two sets of input data; one data-centric and one document-centric. Two practical solutions are presented, one for each input data set:

  • Document Comparator — Uses Java API calls to customise a pre-existing pipeline with a number of extension points.

  • Pipelined Comparator (DXP) — Uses a filter pipeline defined by an XML file called a 'DXP' to customise the comparison.

Document Comparator

Imagine comparing the following two inputs, with the intention of ignoring the change made to the revision attribute of the author, and also the date elements.

Example 2.1: the author information from a DocBook file (See document/documentA.xml in the sample on Bitbucket)

XML
<article xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
  <info>
    <title>Ignore Changes Sample</title>
    <author revision="1.0">
      <personname>Joe Bloggs</personname>
      <address>
        <phone>+44 200 1234 567</phone>
        <email>joe@blogs.com</email>
      </address>
    </author>
  </info>
  <sect1>
    <title>Ignore Changes</title>
    <para><date>20141229</date>The input document for the ignore changes sample.</para>
  </sect1>
</article>

Example 2.2: an updated version with changed telephone numbers and updated dates (See document/documentB.xml in the sample on Bitbucket)

XML
<article xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
  <info>
    <title>Ignore Changes Sample</title>
    <author revision="1.1">
      <personname>Joe Bloggs</personname>
      <address>
        <phone>+44 200 1235 890</phone>
        <email>joe@blogs.co.uk</email>
      </address>
    </author>
  </info>
  <sect1>
    <title>Ignore Changes</title>
    <para><date>20150105</date>The input document for the ignore changes sample.</para>
  </sect1>
</article>

Pipelined Comparator

Comparing the following two inputs, with the intention of ignoring the change made to the <person lastUpdated="01012008"> attribute.

Example 3.1: a small address book (See documentA.xml in the sample on Bitbucket)

XML
<addressBook>
  <person lastUpdated="01012008">
    <log/>
    <name>Joe Blogs</name>
    <telephone>01234 567890</telephone>
    <email>joe@blogs.com</email>
  </person>
</addressBook>

Example 3.2: an updated version of the address book (See documentB.xml in the sample on Bitbucket)

XML
<addressBook>
  <person lastUpdated="01022008">
    <log>
      <lastLoggedIn>01032008</lastLoggedIn>
    </log>
    <name>Joe Blogs</name>
    <telephone>01235 467890</telephone>
    <email>joe@blogs.co.uk</email>
  </person>
</addressBook>

Marking Data to Ignore

Next we need to mark our data to be ignored. This is achieved by placing the deltaxml:ignore-changes attribute on the following:

  • Attribute change: on the appropriate child of deltaxml:attributes which represents the attribute you wish to ignore.

  • Sub-tree change: on the topmost node in the sub-tree with a deltaxml:deltaV2 attribute.

  • Text change: on the deltaxml:textGroup.

By placing the deltaxml:ignore-changes='B,A' attribute, you're instructing apply-ignore-changes.xsl to change the delta of the modification to be unchanged and to copy the B version. The legal values are shown below:

deltaxml:ignore-changes Value

Description

"B,A" or "true"

Default. Copy B if it exists, otherwise copy A.

"A,B"

Copy A if it exists, otherwise copy B.

"A"

Copy A if it exists, otherwise don't output.

"B"

Copy B if it exists, otherwise don't output.

""

Don't copy under any circumstances (but process the subtree if present).

Document Comparator

Writing XSLT stylesheet to add deltaxml:ignore-changes attribute

Example: an XSLT stylesheet to mark parts of the DocBook document to be ignored (See document/mark-ignore-changes.xsl in the sample on Bitbucket)

XML
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:dxa="http://www.deltaxml.com/ns/non-namespaced-attribute"
                xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1"
                xmlns:docbook="http://docbook.org/ns/docbook">

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="deltaxml:attributes/dxa:revision">
    <xsl:copy>
      <xsl:attribute name="deltaxml:ignore-changes" select="'true'"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="docbook:para/docbook:date[@deltaxml:deltaV2]">
    <xsl:copy>
      <xsl:attribute name="deltaxml:ignore-changes" select="''"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

After the delta has been marked with the changes that should be ignored, running apply-ignore-changes.xsl and then propagate-ignore-changes.xsl will process the delta, ignoring the marked data. The filter dx2-extract-version-moded.xsl is imported by apply-ignore-changes.xsl. All of these filters are supplied with versions of XML Compare 5.1 and later.

Pipelined Comparator

Example: an XSLT stylesheet to mark the elements and attributes to be ignored (See mark-ignore-changes.xsl in the sample on Bitbucket)

XML
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:dxa="http://www.deltaxml.com/ns/non-namespaced-attribute"
                xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1">

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="deltaxml:attributes/dxa:lastUpdated">
    <xsl:copy>
      <xsl:attribute name="deltaxml:ignore-changes" select="'B,A'"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="log/lastLoggedIn[@deltaxml:deltaV2]">
    <xsl:copy>
      <xsl:attribute name="deltaxml:ignore-changes" select="'B,A'"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Running the Sample Code

For the resources associated with the first sample, see the Bitbucket repo here. For the Document Comparator specific API and DCP sample, see the Bitbucket repo here.

For both samples, download the sample resources into the DeltaNova release directory under the samples directory. The resources should be located such that they are two levels below the top level release directory that contains the jar files. For example deltaNova-year.x.y.z/samples/IgnoreChanges.

Full instructions for running the sample are given in the file README.md, found in the Bitbucket repo and API settings repo.

Ignore Processing in Further Detail

This section provides some rules and further details about how ignore change processing and particularly how the apply-ignore-changes.xsl filter works.

Every element in the post-comparison XML tree has an 'effective' deltaxml:deltaV2 attribute which (a) specifies which of the inputs it was present in and (b) whether or not the elements were identical, if present in both inputs. An element may also have an ancestor ignore-changes attribute; the closest ancestor is used when determining whether an element is included in the result.

When an element does have an ancestor ignore-changes attribute, the following table specifies whether that element appears in the result:

delta / ignore-changes

''

A

B

A,B

B,A/true

A

B

A=B

A!=B

How to Merge Two Documents Using deltaxml:ignore-changes

This section has been moved to Creating a Merged Document.