Re: [xsl] compare two nodes (the child elements, not the string values) in XSLT 1.0

Subject: Re: [xsl] compare two nodes (the child elements, not the string values) in XSLT 1.0
From: Michel Hendriksen <michel.hendriksen@xxxxx>
Date: Thu, 7 Jul 2011 10:34:09 +0200
Can't you use keys? You could setup a key based on the concatenated
values and see if there is a person for that key.

Michel

On Thu, Jul 7, 2011 at 6:55 AM, Wolfhart Totschnig
<wolfhart@xxxxxxxxxxxxx> wrote:
> Hi,
>
> Thanks to all who responded!
>
> For my particular case, I found a less complicated solution than Wendell's,
> but it's a particular solution, not a general one:
>
> <xsl:variable name="last" select="last"/>
> <xsl:if test="path/person/last=last and (not(first) or
> path/person[last=$last]/first=first) and (not(middle) or
> path/person[last=$last]/middle=middle)">
>
> I am amazed that there is no simple general solution for this kind of
> problem in XSLT 1.0. I thought I must be overlooking something obvious.
XSLT
> 2.0 indeed makes life easier!
>
> Thanks again,
> Wolfhart
>
>
> Wendell Piez wrote:
>>
>> Hi,
>>
>> A generalization of Michael's suggestion is to use a mode in which each
>> element is processed to write strings, and then compare the strings.
>>
>> So:
>>
>> <xsl:variable name="author-string">
>>  <!-- generating an RTF containing a string -->
>>  <xsl:apply-templates select="$author" mode="string"/>
>> </xsl:variable>
>> <xsl:variable name="person-string">
>>  <!-- again -->
>>  <xsl:apply-templates select="$person" mode="string"/>
>> </xsl:variable>
>> <xsl:if test="$author-string = $person-string"> ...
>>
>> You can then manage how each string is generated, for purposes of
>> comparison, using templates matching in the mode. (You will find you need
to
>> do some of this in order, for example, to normalize whitespace.)
>>
>> To compare an author to more than one person, wrap your calls in a
>> template that writes a result string you can test for. So:
>>
>> <xsl:template name="compare-person">
>>  <xsl:param name="author" select="/.."/>
>>  <xsl:param name="person" select="."/>
>>  <xsl:variable name="author-string">
>>    <xsl:apply-templates select="$author" mode="string"/>
>>  </xsl:variable>
>>  <xsl:variable name="person-string">
>>    <xsl:apply-templates select="$person" mode="string"/>
>>  </xsl:variable>
>>  <xsl:if test="$author-string = $person-string"> TRUE </xsl:if>
>> </xsl:template>
>>
>> Then:
>>
>> <xsl:template match="author">
>>  <xsl:variable name="author" select="."/>
>>  <xsl:variable name="compare-result">
>>    <xsl:for-each select="$persons">
>>      <!-- generating an RTF containing a string,
>>           possibly including 'TRUE' -->
>>      <xsl:call-template name="compare-person">
>>        <xsl:with-param name="author" select="$author">
>>      </xsl:call-template>
>>    <xsl:for-each>
>>  </xsl:variable>
>>  <xsl:if test="contains($compare-result,'TRUE')"> ...
>>
>> Note this doesn't tell you which of your persons is (are) the same as your
>> author. For that you have to work harder (there are ways).
>>
>> This little exercise in XSLT 1.0 may well convince you that life is easier
>> under XSLT 2.0.
>>
>> Cheers,
>> Wendell
>>
>> On 7/6/2011 4:22 PM, Michael M|ller-Hillebrand wrote:
>>>
>>> Am 06.07.2011 um 20:54 schrieb Wolfhart Totschnig:
>>>
>>>> I have a seemingly simple xslt problem to which I cannot find the
>>>> solution. I want to test whether the context node, which is an<author>
>>>>  element with the form (first?, middle?, last), is equal to one of a set
>>>> of<person>  elements. By "equal" I mean having the same child elements
and
>>>> values of these elements. At first, I thought it would be as easy as
>>>>
>>>> test="path/person = ."
>>>>
>>>> But then I realized that the "=" operator compares the string values of
>>>> the nodes
>>>
>>> Wolfhart,
>>>
>>> How about this (not very cool):
>>>
>>> test="concat(path/person/first, '|', path/person/first, '|',
>>> path/person/first)
>>>     = concat(first, '|', middle, '|', last)"
>>>
>>> - Michael M|ller-Hillebrand

Current Thread