Hi Mark,
Assuming the element names are as given, and that hence each element has
a unique name, probably the most straightforward approach would be to
key the elements by retrieval using their names. This is largely because
your requirements identify two elements as "the same" if they have the
same name, and can ignore their positions in the document (at least
until it comes to writing your reports).
For purposes of exposition, here's an XSLT 2.0 solution:
<xsl:key name="element-by-name" match="*" use="name()"/>
<xsl:variable name="B" select="document('wheredoyoufind/B.xml')"/>
Then you traverse A to report where elements are missing:
<xsl:template match="*">
<xsl:if test="empty(key('element-by-name',name(),$B)">
... the element is missing from B ...
</xsl:if>
<xsl:apply-templates/>
</xsl:template>
Next to report if values are different. Since you only want to do this
on leaf nodes, use a separate template to match only those:
<xsl:template match="*[empty(*)]">
<xsl:if test=". != key('element-by-name',name(),$B)">
... A has a different value from B ...
</xsl:if>
<xsl:next-match/>
</xsl:template>
The next-match instruction here will (would) then apply the first
template also to the elements that match the second one, so its test is
also performed.
To rewrite this in XSLT 1.0, you have to do two things:
* Since key() can't take a third argument to define the scope of
retrieval, you have to work extra to use the key on document B. So:
<xsl:template match="*">
<xsl:variable name="n" select="name()"/>
<xsl:for-each select="$B">
<xsl:if test="not(key('element-by-name',$n)">
... the element is missing from B ...
</xsl:if>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
Do similarly for the other template.
* Since xsl:next-match is not available in XSLT 1.0, work around this by
giving the template matching * a name, which you can call (by name) from
the other template.
I hope this helps.
Cheers,
Wendell
On 1/20/2012 1:57 PM, Mark Anderson wrote:
Hi Guys
I have an XML comparison XSL that works well for identical XML's; however, I
need to create a version that will compare two slightly dissimilar XML's (whose
structure I do not know--other than root element's name).
One will always be a superset of the other (if different).
For example
A contains
<elements>
<element1>
<element1a>1a</element1a>
<element1b>1b</element1b>
<element1c>1c</element1c>
</element1>
<element2>
<element2a>2a</element2a>
<element2b>2b</element2b>
<element2c>2c</element2c>
</element2>
<element3>
<element3a>3a</element3a>
<element3b>3b</element3b>
<element3c>3c</element3c>
</element3>
</elements>
B Contains
<elements>
<element1>
<element1a>1a</element1a>
<element1b>1b</element1b>
<element1c>1c</element1c>
</element1>
<element3>
<element3a>4a</element3a>
<element3c>4c</element3c>
</element3>
</elements>
I want to iterate through every element and attribute in A, find the
corresponding element in B (if it exists) and compare their values.
For example, the output needs to indicate the following:
element2 is missing
element2/element2a is missing
element2/element2b is missing
element2/element2c is missing
element3/element3b is missing
element3a's value is different
element3b's value is different
Any help greatly appreciated
--
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--