[Top] [All Lists]

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

2020-03-15 11:56:49

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

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


On Sun, Mar 15, 2020 at 6:05 AM Trevor Nicholls

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" 
<xsl:output method="xml" encoding="UTF-8" />

<!-- standard identity template -->

<xsl:template match="*">


    <xsl:apply-templates select="@*" />

    <xsl:apply-templates />



<xsl:template match="@*">

  <xsl:copy-of select="." />


<!-- special case for sections -->
<xsl:template match="section">
    <xsl:attribute name="subsects">
      <xsl:call-template name="checkchildren" />
    <xsl:apply-templates select="@*[name() != 'subsects']" />
    <xsl:apply-templates />

<!-- 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:call-template name="testsections">
    <xsl:with-param name="top" select="$tempstruct" />

<xsl:template match="section" mode="check">


    <xsl:apply-templates mode="check" />



<xsl:template match="title" mode="check">


    <xsl:value-of select="." />



<xsl:template match="included" mode="check">

  <xsl:apply-templates mode="check" />


<xsl:template match="*" mode="check">

  <xsl:element name="{local-name()}">
<!-- <xsl:apply-templates /> -->

<xsl:template name="testsections">

  <xsl:param name="top" />

  <xsl:for-each select="$top/*">
      <xsl:when test="not(child::section)">
      <xsl:when test="child::*[not(self::title)][not(self::section)]">



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



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...
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>