Re: [xsl] How to do macro substitution in XPath?

Subject: Re: [xsl] How to do macro substitution in XPath?
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 2 Dec 2023 16:14:15 -0000
On 02/12/2023 16:36, Roger L Costello costello@xxxxxxxxx wrote:
> Hi Folks,
>
> I am converting prose like this:
>
> If the title = "Path to Power" and the author = "Robert A. Caro" (Lyndon
Baines Johnson (LBJ)), then
> process LBJ as follows
>      action 1
> If the title = "Power Broker" and the author = "Robert A. Caro" (Robert
Moses (RM)), then
> process RM as follows
>      action 2
> Neither LBJ nor RM
>      action 3
>
> I need the XPath to be as like the prose as possible.
>
> Suppose the XPath will operate on XML documents like this:
>
> <Book>
>    <Title>Path to Power</Title>
>    <Author>Robert A. Caro</Author>
> </Book>
>
> Below is one approach to writing the XPath. See the XPath in the
xsl:value-of element. Notice the use of XML ENTITIES.
>
> The advantage of that approach is the XPath looks like the prose.
>
> The disadvantage with that approach is that ENTITIES are not XPath. I need
to stick with pure XPath. What XPath do you recommend?
>
Another option would be


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="3.0"
 B B B  xmlns:xs="http://www.w3.org/2001/XMLSchema";
 B B B  exclude-result-prefixes="#all">

 B B B  <xsl:param name="LBJ" as="function(node()) as xs:boolean"
select="function($node) { $node ! ((/Book/Title eq 'Path to Power') and
(/Book/Author eq 'Robert A. Caro')) }"/>
 B B B  <xsl:param name="RM" as="function(node()) as xs:boolean"
select="function($node) { $node ! ((/Book/Title eq 'Power Broker') and
(/Book/Author eq 'Robert A. Caro')) }"/>

 B B B  <xsl:template match="/">
 B B B B B B B  <xsl:value-of select="
 B B B B B B B B B B B  if ($LBJ(.)) then
 B B B B B B B B B B B B B B B  'action 1'
 B B B B B B B B B B B  else if ($RM(.)) then
 B B B B B B B B B B B B B B B  'action 2'
 B B B B B B B B B B B  else if (not(($LBJ(.)) or ($RM(.)))) then
 B B B B B B B B B B B B B B B  'action 3'
 B B B B B B B B B B B  else
 B B B B B B B B B B B B B B B  'Error'
 B B B B B B B B B B B  "/>
 B B B  </xsl:template>

but then I would of course rather use one function taking the "title"
and the "author" as additional parameters and call them as needed:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema";
exclude-result-prefixes="#all"> <xsl:param name="testTitleAuthor"
as="function(node(), xs:string, xs:string) as xs:boolean"
select="function($node, $author, $title) { $node ! ((/Book/Title eq
'Path to Power') and (/Book/Author eq 'Robert A. Caro')) }"/> <xsl:param
name="LBJ" as="function(node()) as xs:boolean"
select="$testTitleAuthor(?, 'Path to Power', 'Robert A. Caro')"/>
<xsl:param name="RM" as="function(node()) as xs:boolean"
select="$testTitleAuthor(?, 'Power Broker', 'Robert A. Caro')"/>
<xsl:template match="/"> <xsl:value-of select=" if ($LBJ(.)) then
'action 1' else if ($RM(.)) then 'action 2' else if (not(($LBJ(.)) or
($RM(.)))) then 'action 3' else 'Error' "/> </xsl:template>
</xsl:stylesheet>

Current Thread