Re: [xsl] Using node-set variables in predicates (another node comparison question)

Subject: Re: [xsl] Using node-set variables in predicates (another node comparison question)
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 3 Jan 2022 02:42:30 -0000
On Sun, Jan 2, 2022 at 5:58 PM Chris Papademetrious
christopher.papademetrious@xxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Hi Dimitre,
>
> Just some feedback from a novice... For me, this would be difficult to
> remember to determine if a node is in a sequence:
>
>         exists(index-of($seq, $n, id-equal#2))
>
> A one-word operator for this would be easier for me to remember:
>
>         $n in $seq
>         $n is $seq
>



Hi Chris,
An advice for every novice:

(a) If you have a pressing need and want to spend the next 6 - 10 years
waiting, then ask for a new operator... Be ready to hear numerous
explanations why your proposal is a bad idea :)

(b) If you have a pressing need and want to have it resolved today, then
write your own function (and many more useful things while you are waiting
for (a)  above)


Cheers,
Dimitre



>
>
> Hi everyone (again),
>
> I was able to use the [$n intersect $seq] trick again today! And I'm proud
> of how it turned out, so I wanted to share it with you.
>
> I want to remove leading/trailing whitespace from certain DITA block
> elements. For example, I want to turn this:
>
>         <p>   This is some text.</p>
>
> into this:
>
>         <p>This is some text.</p>
>
> But there are two tricky aspects:
>
> 1. The leading/trailing whitespace could be buried in a lower-level inline
> element:
>
>         <p>   Here is some text.</p>
>         <p><b>   Here</b> is some text.</p>
>         <p><b><i>   Here</i></b> is some text.</p>
>
> so I need to match the first effectively rendered descendant text() node
> of these block elements.
>
> 2. Some DITA block elements allow other DITA block elements in them:
>
>         <p>   This is a paragraph element.</p>
>         <li>   This is a list element.</li>
>
>         <li>
>           <p>   This is a paragraph element in a list element.</p>
>         </li>
>
> so I need the sibling-adjacency check to stop at the lowest-level
> enclosing block element.
>
> Here are the templates I came up with:
>
>
>   <!-- look for leading/trailing text() nodes in these block elements -->
>   <xsl:variable name="elements"
> select="//(desc|dt|entry|glossterm|li|p|pre|shortdesc|title)"/>
>
>   <!-- remove leading whitespace from leading text() nodes in block
> elements -->
>   <xsl:template match="text()
>                        [matches(., '^\s+')]
>                        [ancestor::*[. intersect
> $elements][not(descendant::*[. intersect $elements])]]
>                        [not(ancestor-or-self::node()
>                          [ancestor::*[. intersect
> $elements][not(descendant::*[. intersect $elements])]]
>                          [preceding-sibling::node()]
>                         )]">
>     <xsl:variable name="results">
>       <xsl:next-match/>  <!-- apply other templates, if needed -->
>     </xsl:variable>
>     <xsl:value-of select="replace($results, '^\s+', '')"/>
>   </xsl:template>
>
>   <!-- remove trailing whitespace from trailing text() nodes in block
> elements -->
>   <xsl:template match="text()
>                        [matches(., '\s+$')]
>                        [ancestor::*[. intersect
> $elements][not(descendant::*[. intersect $elements])]]
>                        [not(ancestor-or-self::node()
>                          [ancestor::*[. intersect
> $elements][not(descendant::*[. intersect $elements])]]
>                          [following-sibling::node()]
>                         )]">
>     <xsl:variable name="results">
>       <xsl:next-match/>  <!-- apply other templates, if needed -->
>     </xsl:variable>
>     <xsl:value-of select="replace($results, '\s+$', '')"/>
>   </xsl:template>
>
>
> Basically, it goes something like:
>
> Find the text() node:
>
> * That has leading/trailing whitespace
> * That is within a block element that does not contain some other
> lower-level block element
> * That is not itself, or has no ancestor up to (but not including) that
> block element, with a preceding/following sibling
>
> The hardest part was figuring out how to get all ancestors up to the first
> block element, but not past that. The nesting of [descendant::*[...]]
> within [ancestor::*] is probably not the most performant way to do this,
> but it gets the job done.
>
> And by using <xsl:next-match/>, the templates can work together to remove
> both leading and trailing whitespace from the same text() node, if needed.
>
>  - Chris
>
>
> 
>
>

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

Current Thread