Subject: [xsl] test for ancestral attribute returning variant results From: "Trevor Nicholls trevor@xxxxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sun, 24 Oct 2021 17:42:30 -0000 |
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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Configuration file for Sa, Liam R. E. Quin liam | Thread | Re: [xsl] test for ancestral attrib, Graydon graydon@xxxx |
Re: [xsl] Configuration file for Sa, Imsieke, Gerrit, le- | Date | Re: [xsl] test for ancestral attrib, Graydon graydon@xxxx |
Month |