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

Subject: Re: [xsl] template matching with modes, not seeing what I expect
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 16 Mar 2020 08:27:48 -0000
Yes, I often add in the redundant "child::" myself for extra clarity.

I would drop the <xsl:text> here:

> <xsl:otherwise>mixed</xsl:otherwise>

But I know others might disagree.

I feel some resistance to your solution because you're computing counts that
aren't logically necessary, but I think that's purely an aesthetic objection.

Michael Kay
Saxonica

> On 16 Mar 2020, at 07:51, Trevor Nicholls trevor@xxxxxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Hi Wendell and others, thanks for your suggestions.
>
> I'm much more of a mathematician than logician, so I went with the
following, which works, hooray:
>
> <xsl:template name="testsections">
>  <xsl:param name="top" />
>  <xsl:for-each select="$top/*">
>    <xsl:variable name="sects" as="xs:integer" select="count(child::section)"
/>
>    <xsl:variable name="titles" as="xs:integer" select="count(child::title)"
/>
>    <xsl:variable name="all" as="xs:integer" select="count(child::*)" />
>    <xsl:choose>
>      <xsl:when test="$sects = 0"><xsl:text>none</xsl:text></xsl:when>
>      <xsl:when test="$sects + $titles =
$all"><xsl:text>all</xsl:text></xsl:when>
>      <xsl:otherwise><xsl:text>mixed</xsl:text></xsl:otherwise>
>    </xsl:choose>
>  </xsl:for-each>
> </xsl:template>
>
> I know child:: is overkill but I've had so much trouble with this simple
requirement that I thought anything which adds clarity is good.
>
> Thanks again
>
> Stay safe out there
> T
>
> -----Original Message-----
> From: Wendell Piez wapiez@xxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> Sent: Monday, 16 March 2020 7:24
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] template matching with modes, not seeing what I expect
>
> Hey Trevor,
>
> To add to your XPath arsenal, consider also the XPath 2.0 functions
> exists() and empty().
>
> Where you have, for example, not(not(section)), you might wish to rewrite as
not(empty(child::section)) which is indeed the same as exists(child::section).
This might help to expose all the logic.
>
> Additionally, we have operators in XPath 2.0
>
> union - same as | - e.g. (title union section) except - I mentioned (*
except title) intersect  - works as you would expect --
>
> and also the "is" operation for node identity ...
>
> Mulberry Technologies Inc. Quick Reference to XPath 2.0:
> http://mulberrytech.com/quickref/xpath2.pdf
>
> Cheers, Wendell
>
> On Sun, Mar 15, 2020 at 2:07 PM Trevor Nicholls trevor@xxxxxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> wrote:
>>
>> Well the good news is that the simple test example I just created for
>> you did copy the input document, although the subsects attributes were
>> not all correctly filled in. While I work on chasing down the
>> programming error that must be buried in there somewhere, I still have
>> the problem of why my simple example incorrectly sets the attribute.
>>
>> Adding debug content has shown that my test message is correctly
>> constructing the temporary structure, so this problem lies in my tests
>> for the type of content.
>>
>> Given this for $tempstruct:
>>
>> <section>
>>  <title />
>>  <section />
>>  <section />
>> </section>
>>
>> the attribute should be "all"
>>
>> Given this:
>>
>> <section>
>>  <title />
>>  <para />
>>  <table />
>>  <para />
>>  <img />
>> </section>
>>
>> the attribute should be "none"
>>
>> and given this:
>>
>> <section>
>>  <title>
>>  <section />
>>  <section />
>>  <para />
>>  <section />
>> </section>
>>
>> the attribute should be "mixed"
>>
>> The process I am using to try to get this result is ($tempstruct is
>> passed in as the parameter "top"):
>>
>> <xsl:template name="testsections">
>>  <xsl:param name="top" />
>>  <xsl:for-each select="$top/*">
>>    <xsl:choose>
>>      <xsl:when test="not(section)"><xsl:text>none</xsl:text></xsl:when>
>>      <xsl:when test="not(not(section) and
>> not(title))"><xsl:text>all</xsl:text></xsl:when>
>>      <xsl:otherwise><xsl:text>mixed</xsl:text></xsl:otherwise>
>>    </xsl:choose>
>>  </xsl:for-each>
>> </xsl:template>
>>
>> This template correctly identifies the all and none options, but
>> returns "all" instead of "mixed" for the last example.
>>
>> Tested on my full document (which has several hundred sections) I can
>> see that all the "all" sections and all the "none" sections are
>> correct, and all the "mixed" sections are erroneously reported as "all".
>>
>> I thought the test "not(not(section) and not(title))" would be true
>> for all elements that had only title and section children. Evidently
>> that's not true.
>>
>> I tried the test "child::*[not(self::title)][not(self::section)]" as
>> an alternative, but that performed even worse.
>>
>> I've missed some subtlety in evaluating presence and absence of
>> specific child elements, and it's probably in an FAQ somewhere, but if
>> it is I missed it.
>>
>> cheers
>> T
>>
>>
>>
>> -----Original Message-----
>> From: Martin Honnen martin.honnen@xxxxxx
>> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
>> Sent: Monday, 16 March 2020 0:53
>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
>> Subject: Re: [xsl] template matching with modes, not seeing what I
>> expect
>>
>> Am 15.03.2020 um 11:04 schrieb Trevor Nicholls trevor@xxxxxxxxxxxxxxxxxx:
>>
>>> 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.
>>
>>> 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.
>>
>> Can you show us a minimal sample input together with the output you
>> get and then one you want?
>>
>>
>>
>
>
>
> --
> ...Wendell Piez... ...wendell -at- nist -dot- gov...
> ...wendellpiez.com... ...pellucidliterature.org... ...pausepress.org...
> ...github.com/wendellpiez... ...gitlab.coko.foundation/wendell...

Current Thread