473,513 Members | 2,561 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

comparing nodes in xslt

Hi-

Does anyone know a way to compare whether two nodes contain
the same information in xslt (the name, attributes, and all content
recursivly should be the same. I am interested in the case where node
ordering matters, and also the case where it doesn't, but perhaps that
is an advanced topic). Ideally the method should be available to
xpath expressions, so I think that creating new templates which
compare nodes will not work (well, it will if you store the results of
the apply-template in a variable and then use that in an expression,
but this seems way too complex at times, especially since variables
are fixed after they are evaluated).

thanks
-I
Jul 20 '05 #1
5 9527
Hi,

I'm not quite sure this reply will be of any use to you.
This solution only works with nodes with the same ordering.
As far as I know, there are not (yet) Xpath expressions to deal with
node comparison (or operations).

to compare e.g. node[1] and node[2], use :

<xsl:variable name="identical">
<xsl:call-template name="check_identical">
<xsl:with-param name="comp1"><xsl:copy-of
select="//node[1]"/></xsl:with-param>
<xsl:with-param name="comp2"><xsl:copy-of
select="//node[2]"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$identical='true'">nodes completely are
identical</xsl:if>
<xsl:if test="$identical='false'">nodes differ in at least one
aspect</xsl:if>

These 2 templates should be included/inserted in the stylesheet:

<xsl:template name="check_identical">
<xsl:param name="comp1"/>
<xsl:param name="comp2"/>
<xsl:variable name="string1">
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="$comp1"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="string2">
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="$comp2"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$string1=$string2"/>
</xsl:template>

The following template 'stringifies' a given node i.e. convert it to
the ascii equivalent like one would see when opening an xml file with
a text editor.

<xsl:template name="stringify">
<xsl:param name="node"/>
<xsl:for-each select="$node/*/*|$node/*/text()">
<xsl:choose>
<xsl:when test="boolean(local-name())">
&lt;<xsl:value-of select="local-name()"/>
<xsl:variable name="pos" select="position()"/>
<xsl:for-each select="@*">
<xsl:text> </xsl:text><xsl:value-of
select="local-name()"/>="<xsl:value-of select="."/>"
</xsl:for-each>
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="."/></xsl:with-param>
</xsl:call-template>
&lt;/<xsl:value-of select="local-name()"/>&gt;
</xsl:when>
<xsl:otherwise><xsl:value-of
select="normalize-space(.)"/></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>

Joris Gillis
Jul 20 '05 #2
Hi-

Thanks for the reply. I looked into it a bit and found that
in XSLT 2 you can define xpath functions using xslt elements. This
certainly makes a solution like this more reasonable. It does still
leave certain problems like counting repeat nodes in a list.... For
instance, if you wanted to eliminate doubles in a list like this

<list>
<element name="1" />
<element name="2" />
<element name="1" />
<element name="1" />
<element name="1" />
<element name="2" />
</list>

converting to

<list>

<element name"1" count="4" />
<element name="2" count="2" />

</list>

you need to group by element type and then count the number of
elements. Except for very constrained cases this seems to me to be
impossible to do in xslt (yes I know about the muenchian method- it
only works in a constrained case). To do this grouping you need to
first be able to check for node equality (which I think you can do in
xslt 2) and then do the grouping based on the equality (which is
better supported in xslt 2 but still can't do what I describe in this
email).

thanks
-I

Hi,

I'm not quite sure this reply will be of any use to you.
This solution only works with nodes with the same ordering.
As far as I know, there are not (yet) Xpath expressions to deal with
node comparison (or operations).

to compare e.g. node[1] and node[2], use :

<xsl:variable name="identical">
<xsl:call-template name="check_identical">
<xsl:with-param name="comp1"><xsl:copy-of
select="//node[1]"/></xsl:with-param>
<xsl:with-param name="comp2"><xsl:copy-of
select="//node[2]"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$identical='true'">nodes completely are
identical</xsl:if>
<xsl:if test="$identical='false'">nodes differ in at least one
aspect</xsl:if>

These 2 templates should be included/inserted in the stylesheet:

<xsl:template name="check_identical">
<xsl:param name="comp1"/>
<xsl:param name="comp2"/>
<xsl:variable name="string1">
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="$comp1"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="string2">
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="$comp2"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$string1=$string2"/>
</xsl:template>

The following template 'stringifies' a given node i.e. convert it to
the ascii equivalent like one would see when opening an xml file with
a text editor.

<xsl:template name="stringify">
<xsl:param name="node"/>
<xsl:for-each select="$node/*/*|$node/*/text()">
<xsl:choose>
<xsl:when test="boolean(local-name())">
&lt;<xsl:value-of select="local-name()"/>
<xsl:variable name="pos" select="position()"/>
<xsl:for-each select="@*">
<xsl:text> </xsl:text><xsl:value-of
select="local-name()"/>="<xsl:value-of select="."/>"
</xsl:for-each>
<xsl:call-template name="stringify">
<xsl:with-param name="node"><xsl:copy-of
select="."/></xsl:with-param>
</xsl:call-template>
&lt;/<xsl:value-of select="local-name()"/>&gt;
</xsl:when>
<xsl:otherwise><xsl:value-of
select="normalize-space(.)"/></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>

Joris Gillis

Jul 20 '05 #3

in********@hotmail.com (inquirydog) writes:
Hi-

Thanks for the reply. I looked into it a bit and found that
in XSLT 2 you can define xpath functions using xslt elements. This
certainly makes a solution like this more reasonable. It does still
leave certain problems like counting repeat nodes in a list.... For
instance, if you wanted to eliminate doubles in a list like this

<list>
<element name="1" />
<element name="2" />
<element name="1" />
<element name="1" />
<element name="1" />
<element name="2" />
</list>

converting to

<list>

<element name"1" count="4" />
<element name="2" count="2" />

</list>

you need to group by element type and then count the number of
elements. Except for very constrained cases this seems to me to be
impossible to do in xslt (yes I know about the muenchian method- it
only works in a constrained case). To do this grouping you need to
first be able to check for node equality (which I think you can do in
xslt 2) and then do the grouping based on the equality (which is
better supported in xslt 2 but still can't do what I describe in this
email).

What do you mean by
but still can't do what I describe in this email.


?

Your grouping example seems quite simple to do in either XSLT1 or XSLT2,
it might loook a bit simpler in 2 using the explict xsl:for-each-group
mechanism, but it doesn't take much code in either case.

For example in 1.0 it would be:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:key name="x" match="element" use="@name"/>

<xsl:template match="list">
<list>
<xsl:for-each select="element[generate-id()=generate-id(key('x',@name))]">
<element name="{@name}" count="{count(key('x',@name))}"/>
</xsl:for-each>
</list>
</xsl:template>

</xsl:stylesheet>

David
Jul 20 '05 #4
Hi-

The method you describe is the Muenchian Method that I
mentioned in my posting.... And it only works for very simple cases,
where 1). you know ahead of time where the list to be counted is, and
2). where the list items are trivial content (all of the same type).
For instance just change one of the elements by adding content to it

<element name="1"> => <element name="1"><content /></element>

the example counts this as the same type of element as the ones
without content.

I repeat what I stated before- XSLT 1.0 and 2.0 are (I am pretty sure)
not capable of counting repeat nodes in a list in the general case,
where the list can appear anywhere in the node tree and where the
elements in the list are not of some predetermined type (they can
contain arbitrary content). This is a limitation of xslt that I
believe should be fixed in future revisions.

thanks
-I

Your grouping example seems quite simple to do in either XSLT1 or XSLT2,
it might loook a bit simpler in 2 using the explict xsl:for-each-group
mechanism, but it doesn't take much code in either case.

For example in 1.0 it would be:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:key name="x" match="element" use="@name"/>

<xsl:template match="list">
<list>
<xsl:for-each select="element[generate-id()=generate-id(key('x',@name))]">
<element name="{@name}" count="{count(key('x',@name))}"/>
</xsl:for-each>
</list>
</xsl:template>

</xsl:stylesheet>

Jul 20 '05 #5


You say

<element name="1"> => <element name="1"><content /></element>

the example counts this as the same type of element as the ones
without content.

well yes of course because you (and so I) are only grouping on the name
attribute. If you want to consider something else as being a
distinguishing factor then just include it in the test eg
use
concat(@name,':',count(*))
would distinguish nodes based on their name attribute and the number of
children. I suspect that you want a test that is more like deep-equal
(which is a predefined function in xpath2) so perhaps your request
This is a limitation of xslt that I
believe should be fixed in future revisions.


has been granted in Xpath2. If that is the case you probably can't express that as
a single Xpath in Xpath 1 (without using an extension function,) but you
can certainly express it in xslt1 so you can do the grouping, you
probably just can't use the optimisation of using a key as the key index
needs to be expressed as a single xpath. But keys are only an
optimisation feature anything expressable using keys is expressable
without them (just may take longer to run)

of course any xpath extension that allows xpath functions to be defined
using xslt would allow this kind of key to be used even in an xslt1
context (saxon and the exslt project have such function definition
possibilitiesfor xslt1, and they are a standard part of xslt2 draft)

David
Jul 20 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1959
by: Erhard Schwenk | last post by:
Hi there, Maybe this is a faq, if so, point me the URL please. I have to do some xml to xml transformations in xslt, where I have - simplified - the following: input: <doc>...
2
7940
by: Claudio Jolowicz | last post by:
How can XSLT stylesheets be used to edit, remove and add nodes specified by their position in the document tree? The XML document stores development tasks in a hierarchical way, i.e. tasks can...
3
3651
by: Andy Fish | last post by:
Hi, I just found this template in someone else's xslt (it's Microsoft's "word2html" stylesheet to convert WordProcessingML to HTML) <xsl:template match="WX:sect"> <xsl:variable...
1
6695
by: XmlAdoNewbie | last post by:
Hi All, I am just wondering if there is a way to compare 2 XML nodes to see if the data between them is the same? The structure of the XML nodes are exactly the same I just want to know if the...
4
5521
by: ddd | last post by:
I am trying to build a diff tool that allows me to compare two HTML files. I am looking for resources on how to achive this. The main problem is that I do not want to simply highlight the line of...
2
1517
by: Ryan Adler | last post by:
I have a terrible headache from this problem. Perhaps someone can help. My XML is formatted like this: <events> <event> <starts-at>123456<starts-at/> <event> ... <events/>
1
1521
by: Chris | last post by:
I have a problem with grouping elements in my XSL. What I want to do is select all of the distinct SCE_CGPC records, then by the FSG_SNAM records for each SCE_CGPC and then again by MOA_NAME for...
3
2043
by: tschwartz | last post by:
I'm trying to write a stylesheet which removes nodes which are empty as a result of other template processing. For example, given the following xml, I'd like to: - remove all "b" elements -...
2
2254
by: Ryan Nordman | last post by:
Hey XML gurus, Is there a way to write a template so that it will compare two XML subtrees wholesale? I can't quite get my head around this problem. Let's say I have these two XML trees, both...
0
7259
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7158
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7380
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7535
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7098
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5683
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5085
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4745
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
1592
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.