This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Merging XML
- To: xsl-list at mulberrytech dot com
- Subject: Re: Merging XML
- From: Tom Mullen <Tom dot Mullen at reuters dot com>
- Date: Fri, 04 Aug 2000 14:20:55 +0000 (GMT)
- Autoforwarded: false
- Disclose-recipients: prohibited
- Hop-count: 2
- Reply-To: xsl-list at mulberrytech dot com
- Sensitivity: Company-Confidential
Josh,
using the examples you gave:
>1.xml:
> <A>
> <B name="123">
> <C>
> <D>
> <E>val 1</E>
> </D>
> </C>
> <G>1</G>
> </B>
> </A>
>2.xml:
> <A>
> <B name="123">
> <H>
> <F>
> Val3
> </F>
> </H>
> <C>
> <D>
> <E> Val2 </E>
> </D>
> </C>
> </B>
> </A>
>
>
>If I rearrange the order to put <A><B><C>.. instead of <A><B><H>..
>it works.
>
Then the following xsl doc treats both 2) and its rearranged form the same.
A few warnings:
1) Anybody who knows anything about XSL will recognise this as being
written by a newbie. (any comments at all on it would be most welcome)
2) I think there needs to be some form of ignore whitespace setting (I get
that there is a difference in B when there isn't)
3) This xsl only works with the format of the XML documents above. I think
a generic solution would be an order of magnitude more difficult (anybody
prepared to take up the gauntlet?).
4) Only a difference html is produced, I haven't got round to installing
<xsl:copy> and/or <xsl:copy-of> at the appropriate points. However, this
example should explain the approach a little more clearly.
5) Apologies in advance for the lack of comments
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="oldfile" />
<xsl:variable name="old" select="document($oldfile)" />
<xsl:variable name="new" select="/" />
<xsl:template match="/A">
<html>
<head><title>Comparison</title></head>
<body>
<h1>Comparison</h1>
<xsl:comment><xsl:value-of select="$new/"/></xsl:comment>
<xsl:comment><xsl:value-of select="$old/"/></xsl:comment>
<xsl:comment><xsl:value-of select="$oldfile"/></xsl:comment>
<xsl:call-template name="compall">
<xsl:with-param name="new" select="$new" />
<xsl:with-param name="old" select="$old" />
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="compall">
<xsl:param name="old" />
<xsl:param name="new" />
<xsl:variable name="oldval" select="$old/text()"/>
<xsl:variable name="newval" select="$new/text()"/>
<xsl:if test="not((string-length($oldval)=string-length($newval)) and
contains($oldval,$newval))">
<xsl:comment>different vals</xsl:comment>
<xsl:variable name="oldname" select="name($old)" />
<xsl:variable name="newname" select="name($new)" />
<p>Altered NEW:<xsl:value-of select="$newname"/>=<xsl:value-of
select="$newval"/></p>
<p>Altered OLD:<xsl:value-of select="$oldname"/>=<xsl:value-of
select="$oldval"/></p>
</xsl:if>
<xsl:call-template name="list-additional">
<xsl:with-param name="head">Added:</xsl:with-param>
<xsl:with-param name="more" select="$new" />
<xsl:with-param name="less" select="$old" />
</xsl:call-template>
<xsl:call-template name="list-additional">
<xsl:with-param name="head">Removed:</xsl:with-param>
<xsl:with-param name="more" select="$old" />
<xsl:with-param name="less" select="$new" />
</xsl:call-template>
<xsl:call-template name="list-compare">
<xsl:with-param name="old" select="$old" />
<xsl:with-param name="new" select="$new" />
</xsl:call-template>
</xsl:template>
<xsl:key name="logs" match="B" use="@name" />
<xsl:template name="list-additional">
<xsl:param name="head" />
<xsl:param name="more" />
<xsl:param name="less" />
<ul>
<xsl:if test="$more/B">
<xsl:for-each select="$more/B">
<xsl:variable name="item" select="." />
<!-- select the 'less' document so that the key indexes into that
document -->
<xsl:for-each select="$less">
<xsl:if test="not(key('logs', $item/@name))">
<xsl:comment><xsl:value-of select="$item"/></xsl:comment>
<li><xsl:value-of select="$head"/><xsl:apply-templates
select="$item" mode="describe" /></li>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:for-each select="$more/*">
<xsl:variable name="item" select="." />
<xsl:variable name="itemname" select="name(.)" />
<xsl:choose>
<xsl:when test="self::B"/>
<xsl:otherwise>
<xsl:comment>looking for <xsl:value-of select="$itemname"/></xsl:comment>
<xsl:choose>
<xsl:when test="$less/*[name()=name($item)]"/>
<xsl:otherwise>
<xsl:comment><xsl:value-of select="$item"/></xsl:comment>
<li><xsl:value-of select="$head"/><xsl:apply-templates
select="$item" mode="describe" /></li>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="list-compare">
<xsl:param name="old" />
<xsl:param name="new" />
<xsl:variable name="oldname" select="name($old)" />
<xsl:variable name="newname" select="name($new)" />
<ul>
<xsl:if test="$old/B">
<xsl:for-each select="$old/B">
<xsl:variable name="old2" select="." />
<xsl:for-each select="$new">
<xsl:if test="key('logs', $old2/@name)">
<xsl:variable name="new2" select="key('logs', $old2/@name)"/>
<xsl:call-template name="compall">
<xsl:with-param name="new" select="$new2" />
<xsl:with-param name="old" select="$old2" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:for-each select="$old/*">
<xsl:variable name="old2" select="." />
<xsl:variable name="old2name" select="name(.)" />
<xsl:choose>
<xsl:when test="self::B"/>
<xsl:otherwise>
<xsl:comment>looking for <xsl:value-of select="$old2name"/></xsl:comment>
<xsl:variable name="new2" select="$new/*[name()=$old2name]"/>
<xsl:if test="$new/*[name()=name($old2)]">
<xsl:variable name="newval" select="$new2/self::text()"/>
<xsl:variable name="oldval" select="$old2/self::text()"/>
<xsl:comment>New val=<xsl:value-of select="$newval"/>Old
val=<xsl:value-of select="$oldval"/></xsl:comment>
<xsl:call-template name="compall">
<xsl:with-param name="new" select="$new2" />
<xsl:with-param name="old" select="$old2" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="*" mode="describe">
<xsl:value-of select="name()" /><xsl:text>=</xsl:text><xsl:value-of
select="text()" />
</xsl:template>
<xsl:template match="B" mode="describe">
<xsl:text>B-</xsl:text><xsl:value-of select="@name" />
</xsl:template>
</xsl:stylesheet>
Thanks
Tom
-----------------------------------------------------------------
Visit our Internet site at http://www.reuters.com
Any views expressed in this message are those of the individual
sender, except where the sender specifically states them to be
the views of Reuters Ltd.
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list