Re: the "~" operator (was Re: [xsl] Add id to next element)

Subject: Re: the "~" operator (was Re: [xsl] Add id to next element)
From: "Chris Papademetrious christopher.papademetrious@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 23 May 2022 11:08:43 -0000
Hi everyone,

I found another case where the ~ operator might have been useful.

In the following XML:

====
<body>
  <p/>
  <p outputclass="foo bar"/>
  <p outputclass="foo BAZ"/>
</body>
====

I want to add "BAZ" to p/@outputclass, without adding duplicate values of BAZ.
Right now I can do this with an extra user-defined function to add a string to
a sequence:

====
  <xsl:template match="p">
    <xsl:copy>
      <xsl:attribute name="outputclass"
        select="tokenize(@outputclass, '\s+')
          => mine:add_value('BAZ')
          => distinct-values()
          => string-join(' ')"/>
      <xsl:apply-templates select="node()|(@* except @outputclass)"/>
    </xsl:copy>
  </xsl:template>

  <xsl:function name="mine:add_value">
    <xsl:param name="values" as="xs:string*"/>
    <xsl:param name="new_value" as="xs:string"/>
    <xsl:sequence select="($values, $new_value)"/>
  </xsl:function>
====

But if the ~ operator were available, I think I could have done the value
addition natively (maybe?) instead of with a function:

====
  <xsl:template match="p">
    <xsl:copy>
      <xsl:attribute name="outputclass"
        select="tokenize(@outputclass, '\s+')
          => (~, 'BAZ')
          => distinct-values()
          => string-join(' ')"/>
      <xsl:apply-templates select="node()|(@* except @outputclass)"/>
    </xsl:copy>
  </xsl:template>
====

(In the real code, this happens in the middle of the template with a computed
string value to add, so adding a test for existing values to the template
match is not an option.)

 - Chris

Current Thread