This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Comparing nodes minus one child


Matt--

It seems to me you have two separable problems here. One is establishing 
how you know that one <A> "equals" another. This is what you first ran up 
against: it's an area in XSLT where care must be taken, because XSLT 
doesn't really compare node sets as such, but reduces their comparison to 
string comparisons (saying they're equal if they contain nodes whose string 
value is equal). Given a process whereby you build a Result Tree Fragment 
from each <A> which represents what it "is" for purposes of your comparison 
(for example, that you don't pick up <X> children), you can compare RTFs. 
Since they really compare only their string values, there are potentially 
problems due to the fact that node hierarchies that are differently 
structured, can be equal when considered as strings. (Mike warned about 
this.) The mode-based routine I suggested to build RTFs gave a way to work 
around that.

That's problem #1, which I'm assuming you've got licked. Problem #2 is how 
to expedite the actual comparison efficiently. You are quite right to 
suspect it's a cumbersome operation, since it seems that for each <A> in 
one group, you need to go through all the <A>s in the other group.

But maybe there is a way to optimize this just a bit, since you actually 
don't need to go through *all* the <A>s in the second group for each <A> in 
the first -- since your action, if you get a hit, is just to copy, and 
presumably you only need to do this once. Therefore you only need to go 
until you either (1) get a match, or (2) run out of <A>s in the second 
group to compare.

This suggests that a recursive solution is possible. Define your comparison 
variable RTF, then pick up the first <A> in the second group to compare; if 
it compares truly, copy it and quit. If not and there's a next <A> in the 
second group, pick it up and repeat; if there's not, you're done.

You haven't provided enough code infrastructure for me to be able to code 
this up properly: but that's okay, since I don't really have time to do 
that anyway. But there are some experts in recursive processing on this 
list who could certainly implement this (and even come up with more 
efficient alternatives).

Another thing to consider would be a two-pass solution: that could be 
quicker too. The first pass would reduce both your sets of <A>s to their 
comparison version, so you could compare them directly, and not have to 
reduce the second set multiple times (that is, each time you have a new <A> 
from the first set to compare). The second pass would do the comparison, 
and when there's a hit, go back to the first source document (using the 
document() function probably) to get the entire <A>. This can also be done 
in a single stylesheet if you are willing to use a node-set extension function.

I hope I've understood your problem well enough to suggest ways to go about it.

Cheers,
Wendell

At 12:36 PM 9/28/01, you wrote:
>Assume that I have two collections of elements <A>(stored in variables)
>that I have gotten from two different files.
>The collections look something like the following
><HOLDER>
>      <A>
>           <B>..</B>
>           <C>..</C>
>           ...
>           <X>..</X>
>      </A>
></HOLDER>
>
>I want to see if each of the <A> elements in the <HOLDER>(from first
>collection) equals an <A> in the <HOLDER>(from the second collection), but
>I want the comparison to only include the <A> with all of its children
>EXCEPT the <X> element.
>My goal is to output the entire <A> element (including the <X> element).
>
>I can get rid of the <X> elements by calling the following templates:
><xsl:template match="node()|@*" mode="remove">
>      <xsl:copy>
>           <xsl:apply-templates select="node()|@*" mode="remove"/>
>      </xsl:copy>
></xsl:template>
><xsl:template match="X"mode="remove">
>      <!-- do nothing, we don't want this element in the result -->
></xsl:template>
>
>I know that I can convert each set of <A> elements in both collections to
>the compressed version.  Then I would have to iterate through all of the
>original <A> elements, compressing that individually, and then comparing it
>to the results of the compress second collection. (I also need to do it
>going through the second list as well, since I am doing Adds, Deletes,
>etc.).  Is there a way to do this more effiently?


======================================================================
Wendell Piez                            mailto:wapiez@mulberrytech.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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]