Loading login details...

How to ignore changes

The XML files that you are comparing may contain data that you expect to change. You may wish to ignore these changes. From release 5.1 of DeltaXML Core, XSLT filters are provided to allow you to ignore selected changes. This makes it easy to generate some forms of output from the delta file. The last section in this document describes some use cases for this which allow you to "merge" two documents in a controlled way.

What does "ignore" really mean?

First, we need to ask the question: What is meant by "ignore"?

Consider this very simple example of attribute change:

Input 1:

<x y='1'/> 

Input 2:

<x y='2'/>

Ignore could mean:

  1. remove it completely from the result: <x/>
  2. prefer the 'A' or 'old' value: <x y='1'/>
  3. prefer the B or new value: <x y='2'/>
  4. take the average of any values with numerical/time data types: <x y='1.5'/>
  5. put in a difference marker: <x y='changed'/>
  6. find some way to represent them both: <x y='1|2'/> 

All of these approaches are possible using an output filter, however this document will concentrate on a generic approach and describe filters included in DeltaXML Core since release 5.1 which implement the first three strategies above.

Worked example

Imagine comparing the following two inputs, with the intention of ignoring the change made to the lastUpdated attribiute:

Document A:

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

Document B:

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

DeltaXML Core will produce the following delta:

<addressBook xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1"
             xmlns:dxx="http://www.deltaxml.com/ns/xml-namespaced-attribute"
             xmlns:dxa="http://www.deltaxml.com/ns/non-namespaced-attribute"
             deltaxml:deltaV2="A!=B"
             deltaxml:version="2.0"
             deltaxml:content-type="full-context">
   <person deltaxml:deltaV2="A!=B">
      <deltaxml:attributes deltaxml:deltaV2="A!=B">
         <dxa:lastUpdated deltaxml:deltaV2="A!=B">
            <deltaxml:attributeValue deltaxml:deltaV2="A">01012008</deltaxml:attributeValue>
            <deltaxml:attributeValue deltaxml:deltaV2="B">01022008</deltaxml:attributeValue>
         </dxa:lastUpdated>
      </deltaxml:attributes>
      <log deltaxml:deltaV2="A!=B">
         <lastLoggedIn deltaxml:deltaV2="B">01032008</lastLoggedIn>
      </log>
      <name deltaxml:deltaV2="A=B">Joe Blogs</name>
      <telephone deltaxml:deltaV2="A!=B">
         <deltaxml:textGroup deltaxml:deltaV2="A!=B">
            <deltaxml:text deltaxml:deltaV2="A">01234 567890</deltaxml:text>
            <deltaxml:text deltaxml:deltaV2="B">01235 467890</deltaxml:text>
         </deltaxml:textGroup>
      </telephone>
      <email deltaxml:deltaV2="A!=B">
         <deltaxml:textGroup deltaxml:deltaV2="A!=B">
            <deltaxml:text deltaxml:deltaV2="A">joe@blogs.com</deltaxml:text>
            <deltaxml:text deltaxml:deltaV2="B">joe@blogs.co.uk</deltaxml:text>
         </deltaxml:textGroup>
      </email>
   </person>
</addressBook>

This is the changes represented in our deltaV2 format. While this may look overly complicated for such a simple change, it makes our job of processing it a lot easier. A side-effect of attribute changes being represented as elements is the addition of the dxa namespace, this is due to the namespace of a non-qualified attribute not being that of the document but an anonymous one and so this anonymous namespace needs to be represented. The implication of this is that when promoting this attribute we need to make sure that attribute gets placed in the correct namespace.

Marking data that needs to be ignored

Next we need to mark our data to be ignored, this is achieved by placing the deltaxml:ignore-changes=‘true’ attribute on the following:

By placing the deltaxml:ignore-changes='true' attribute, you’re instructing apply-ignore-changes XSLT to change the delta of the modification to be unchanged and to copy the new (B) version. If there is no new version (i.e. in the case of a deletion) the old (A) version is used. This behaviour can be controlled by using a different value for the deltaxml:ignore-changes attribute, the legal values are shown below:

deltaxml:ignore-changes Value

Description

"B,A" or "true"

Default. Copy new value if it exists, otherwise copy old value.

"A,B"

Copy old value if it exists, otherwise copy new value.

"A"

Copy old value if it exists, otherwise don’t output

"B"

Copy new value if it exists, otherwise don’t output

""

Don’t copy if modified.

The ignore-changes attribute can be added using an XSLT stylesheet, an example for ignoring changes to the lastUpdated attribute is included below:

<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" value="true"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

After the delta has been marked with the changes that should be ignored, using a filter similar to the one above, running apply-ignore-changes.xsl and then propagate-ignore-changes.xsl will process the delta, ignoring the marked data. Both of these filters are supplied with versions of DeltaXML Core 5.1 and later.

The example used in this document is available for your own experimentation in the samples directory of the DeltaXML Core release in versions 5.1 and above. The sample shows how to ignore both element and attribute change and provides and example of how to construct the pipeline of appropriate output filters described here.

Other use cases for deltaxml:ignore-changes

This method of ignoring changes is a very powerful feature. For example, if you place the attribute deltaxml:ignore-changes="A" on any element within the document, this will generate the old version of the whole of that element, ignoring any changes made to that particular element.

If you place the attribute deltaxml:ignore-changes="B,A" on the root element, then you will get a merge of the two documents. Where there is a conflict, for example an attribute where the value is different in the two documents, the value of the new document will be taken in preference to the value of the old document. Again, this applies if you place this attribute on any subtree of the document. To merge the two documents with the old document taking priority, just add the attribute deltaxml:ignore-changes="A,B" on the root element.

In this way, you could easily generate a new document which consists of an intelligent merge of the two original documents, using the old or new values at any point in the document hierarchy. All you need to do is to add the deltaxml:ignore-changes attributes at appropriate places within the delta document.

Note that the attribute will apply to all of the elements in a subtree. For example, if you place deltaxml:ignore-changes on the root element then  this will override deltaxml:ignore-changes anywhere else in the document.