xsl-list
[Top] [All Lists]

Re: [xsl] test for ancestral attribute returning variant results

2021-10-24 14:03:05
Haven't gone deep into this (and after a single reading I am not sure I
understand what is the alleged problem at all), but at a glance it seems
quite possible that the use of the "!=" operator may be the culprit of some
unexpected behavior.

 My advice is to always use the not() function instead of the "!="
operator, unless one is absolutely certain "!=" is really needed.

Thanks,
Dimitre

On Sun, Oct 24, 2021 at 10:42 AM Trevor Nicholls 
trevor(_at_)castingthevoid(_dot_)com <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hi



(What follows is XSL 2.0 and the processor I am using is Saxon, I have
tried with Saxon versions 8.7.3, 9.9 and 10.0 and all exhibit the same
behaviour.)



I am at a complete loss to explain why this is happening.



My XML documents conform to a schema which allows many elements to have a
'version' attribute. An element's version serves as a default for all
descendants, although it can be overridden on any descendant subtree by
another version on the descendant node. In many cases an element will have
an unnecessary version specified (because it is the same as the nearest
ancestral version).



I have a named template (versiontest) which is called on elements to
construct a version callout in the margin. The version should appear if it
is different to that of the parent, or if the ancestral element with the
same version appears on an earlier page.



My problem is that this template is generating different output depending
on the size of the containing document.



Here's the pertinent XML fragment:



<note version="8.00">

  <para version="8.00">blah blah blah.</para>

  <para version="8.00">blah blah blah.</para>

</note>



The para versions are superfluous, and their presence triggers the
problem, but (a) these documents are not created by me, (b) my code should
cope with superfluous versions anyway, and (c) my code works in smaller
documents.



This is the versiontest template, it should either generate nothing or
output a version string. I've added a few debug lines which I hoped would
clarify the situation (spoiler alert, they don't).



<xsl:template name="versiontest">

<!--

  -- @version is this node's version

  -- $ancvers is the nearest ancestral version, found on node $ancv

  -- the nearest ancestral page break is on node $ancpg

  -- $versdepth is the depth of $ancv from the root

  -- $pgdepth is the depth of $ancpg from the root

  -- We output the version IF @version is different to $ancvers,

  -- OR IF @version matches $ancvers but $versdepth is less than $pgdepth

  -- Note: if versdepth > pgdepth then the version will have appeared
earlier in the page,

  -- if versdepth < pgdepth then it will have appeared on a previous page,

  -- while if versdepth = pgdepth then the version will appear at the top
of the current page

-- >

<!-- DEBUG 1

  <xsl:message select="concat('1 element=', local-name(), ', version=',
@version)" />

END DEBUG 1 -- >

  <xsl:variable name="ancv" select=ancestor::*[@version][1]" />

  <xsl:variable name="ancvers" select="$ancv/@version" />

  <xsl:variable name="ancpg" select="ancestor::*[local-name() = 'section'
and @break='Y'][1]" />

  <xsl:variable name="versdepth">

    <xsl:for-each select="$ancv">

      <xsl:value-of select="count(ancestor-or-self::*)" />

    </xsl:for-each>

  </xsl:variable>

  <xsl:variable name="pgdepth">

    <xsl:for-each select="$ancpg">

      <xsl:value-of select="count(ancestor-or-self::*)" />

    </xsl:for-each>

  </xsl:variable>

<!-- DEBUG 2

   <xsl:message>

     <xsl:value-of select="concat('2 ancvers=', $ancvers, ', versdepth=',
$versdepth, ', pgdepth=', $pgdepth)" />

     <xsl:value-of select="concat('[', count(ancestor::*[@version]), ':
')" />

    <xsl:for-each select="ancestor::*[@version]">

    <xsl:value-of select="concat('(', ./@version, ')')" />

   </xsl:for-each>

   <xsl:text>]</xsl:text>

  </xsl:message>

END DEBUG 2 -- >

  <xsl:if test="@version != ''">

    <xsl:if test="@version != $ancvers or not($versdepth > $pgdepth)">

<!-- DEBUG 3

  <xsl:message select="concat('3 output version=', @version)" />

END DEBUG 3 à

      <xsl:value-of select="@version" />

    </xsl:if>

  </xsl:if>

<xsl:template>



In a smallish document, the versiontest template outputs "8.00" for the
note element and nothing for the para elements. In a large document it
outputs "8.00" for all three elements.



With the debug statements included, the small document generates these
messages



1 element=note, version=8.00

2 ancvers=, versdepth=, pgdepth=3 [0:]

3 output version=8.00

1 element=para, version=8.00

2 ancvers=8.00, versdepth=5, pgdepth=3 [1: (8.00)]

1 element=para, version=8.00

2 ancvers=8.00, versdepth=5, pgdepth=3 [1: (8.00)]



I wondered if the larger document might include earlier "versioned"
subtrees that triggered a flaw in my logic, but evidently not. If this was
the cause, there would be more versions listed in the message labelled
DEBUG 2.

The large document generates these messages



1 element=note, version=8.00

2 ancvers=, versdepth=, pgdepth=8 [0:]

3 output version=8.00

1 element=para, version=8.00

2 ancvers=8.00, versdepth=10, pgdepth=8 [1: (8.00)]

3 output version=8.00

1 element=para, version=8.00

2 ancvers=8.00, versdepth=10, pgdepth=8 [1: (8.00)]

3 output version=8.00



I can't see where the tests between DEBUG 2 and DEBUG 3 are going wrong;
certainly if you plug in the values reported in the messages then the
results should be those reported in the smaller documents, not what I'm
actually seeing.



I'm hoping there's a flaw in my logic which is obvious to a more
experienced eye, but I'm afraid I can't see it myself.



You're going to ask for a small failing test case; unfortunately there
isn't one :-(



Cheers

T










XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
email <>)



-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they write
all patents, too? :)
-------------------------------------
Sanity is madness put to good use.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>