Re: [xsl] template matching with modes, not seeing what I expect

Subject: Re: [xsl] template matching with modes, not seeing what I expect
From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 15 Mar 2020 16:56:43 -0000
Trevor,

I agree with Martin: the behavior you describe doesn't add up, as you
have yourself observed, which makes me think the issue is somewhere
else. Making a small, standalone and replicable example of input,
desired output, and current approach, might possibly reveal the issue
on its own, and if not, would not be wasted effort, since it helps us
see as well.

Meanwhile, check out the 'except' operator

@* except @subsects - all attributes except subsects attributes
* except (title|section) - all child elements except title and section
children

Also due diligence in this case would be namespaces - there is enough
context-switching going on - plus free-form generation of results w/
xsl:element etc. - that if namespaces are part of the picture, all
your other bets are off. So double-check to make sure any namespaces
are accounted for because they *will* throw off your XPath. (Any
namespaces on source data is part of what you are not showing us
here.)

Either way, reducing this to a mini example would be instructive.

Cheers,
Wendell


On Sun, Mar 15, 2020 at 6:05 AM Trevor Nicholls
trevor@xxxxxxxxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
wrote:
>
> In these difficult times I hope everybody reading this is safe and well and
stays that way.
>
>
>
> I'm testing a simple stylesheet which implements a suggestion made in reply
to my previous approach, i.e. that I could process the output of a document
into a variable to test. When the stylesheet is just reporting the results, it
works just fine, but when I combine it with templates which copy the input
document and replace one attribute based on those tests, the input document is
not being copied.
>
>
>
> Sorry that the question comes at the bottom of quite a long message.
>
>
>
> Here's the stylesheet
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> <xsl:output method="xml" encoding="UTF-8" />
>
> <!-- standard identity template -->
>
> <xsl:template match="*">
>
>   <xsl:copy>
>
>     <xsl:apply-templates select="@*" />
>
>     <xsl:apply-templates />
>
>   </xsl:copy>
>
> </xsl:template>
>
>
>
> <xsl:template match="@*">
>
>   <xsl:copy-of select="." />
>
> </xsl:template>
>
> <!-- special case for sections -->
> <xsl:template match="section">
>   <xsl:copy>
>     <xsl:attribute name="subsects">
>       <xsl:call-template name="checkchildren" />
>     </xsl:attribute>
>     <xsl:apply-templates select="@*[name() != 'subsects']" />
>     <xsl:apply-templates />
>   <xsl:copy>
> </xsl:template>
>
> <!-- check what sort of section it is: has only a title and sections, has no
sections, or is mixed -->
> <!-- build a cut down copy of the structure in a variable and test that-->
> <xsl:template name="checkchildren">
>   <xsl:variable name="tempstruct">
>     <xsl:element name="section">
>      <xsl:apply-templates mode="check" />
>     </xsl:element>
>   </xsl:variable>
>   <xsl:call-template name="testsections">
>     <xsl:with-param name="top" select="$tempstruct" />
>   </xsl:call-template>
> </xsl:template>
>
> <xsl:template match="section" mode="check">
>
>   <section>
>
>     <xsl:apply-templates mode="check" />
>
>   <section>
>
> </xsl:template>
>
>
>
> <xsl:template match="title" mode="check">
>
>   <title>
>
>     <xsl:value-of select="." />
>
>   </title>
>
> </xsl:template>
>
>
>
> <xsl:template match="included" mode="check">
>
>   <xsl:apply-templates mode="check" />
>
> </xsl:template>
>
>
>
> <xsl:template match="*" mode="check">
>
>   <xsl:element name="{local-name()}">
> <!-- <xsl:apply-templates /> -->
>   </xsl:element>
> </xsl:template>
>
> <xsl:template name="testsections">
>
>   <xsl:param name="top" />
>
>   <xsl:for-each select="$top/*">
>     <xsl:choose>
>       <xsl:when test="not(child::section)">
>         <xsl:text>none</xsl:text>
>       </xsl:when>
>       <xsl:when test="child::*[not(self::title)][not(self::section)]">
>
>        <xsl:text>all</xsl:text>
>       </xsl:when>
>       <xsl:otherwise>
>         <xsl:text>mixed</xsl:text>
>       </xsl:otherwise>
>     </xsl:choose>
>   </xsl:for-each>
> </xsl:template>
>
> </xsl:stylesheet>
>
>
>
> As I understand it, the above stylesheet should copy its input XML exactly,
adding or adjusting the subsects attribute on every section element to reflect
whether (apart from a title) it contains only sections, no sections, or a
mixture.
>
>
>
> But if I run this stylesheet and give it an input file (with no subsects
attributes) which contains a parent with multiple sections and mixed content,
only the first section is output with the attribute (incorrectly set to
"none"), and the rest of the output XML is the result of the mode="check"
versions of the templates, i.e. the only output is the initial XML header
followed by a copy of the $tempstruct variable built when the context node is
the top level element of the input document.. The default templates simply
aren't executed.
>
>
>
> If I remove the identity template, and instead of copying the document and
filling in the new attribute, change checkchildren to output the values for
each section as text nodes, it behaves as I'd expect.
>
>
>
> By putting a message into the <xsl:template match="*"> template (the one
without a mode) I have verified that this particular template is executed
exactly once: for the path /document/title.
>
>
>
> Have I misunderstood how modes work? Is there a coding error that I haven't
noticed? The XSL processor is Saxon and the stylesheet is XSL 2.0.
>
>
>
> Take care out there
>
>
>
> Cheers
>
> T
>
>
>
>
>
>
>
> XSL-List info and archive
> EasyUnsubscribe (by email)



--
...Wendell Piez... ...wendell -at- nist -dot- gov...
...wendellpiez.com... ...pellucidliterature.org... ...pausepress.org...
...github.com/wendellpiez... ...gitlab.coko.foundation/wendell...

Current Thread