1

I am outputting the name node of each property node in a ; delimited string as following:

<xsl:value-of select="properties/property/name" separator=";" />

I want to alter this such that each element is prefixed with _. An example output should be:

_alpha;_beta;_gamma

I tried the following:

<xsl:value-of select="concat('_', properties/property/name)" separator=";" />

I want to use this to create an output node containing that string:

<my_node>
    <xsl:value-of select="concat('_', properties/property/name)" separator=";" />
</my_node>

This gives an error when there are multiple properties:

XPTY0004: A sequence of more than one item is not allowed
          as the second argument of fn:concat() (<name>, <name>)

Is there a way to get this working in XSLT 2.0/3.0?

I could resort to the XSLT 1.0 for-each solution as given in https://stackoverflow.com/a/57856287/12042211 (in which we are manually adding the separator), but I am wondering if something elegant in XSLT 2.0/3.0 is possible.

2 Answers2

3

The answer is yes. XSLT 2.0 allows you to write expressions like this...

<xsl:value-of select="properties/property/concat('_', name)" separator=";" />

So, for each property it selects the concatenation of "_" with the name element.

Such syntax is not valid in XSLT 1.0 though.

Tim C
  • 70,053
  • 14
  • 74
  • 93
1

In XSLT 3.0 I would tend to write this as

<xsl:value-of select="properties/property ! ('_' || name)" separator=";" />

and perhaps use string-join() instead of xsl:value-of. You haven't shown the context, but try to use xsl:value-of only when you really want a text node, not when you just want a string.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thank you. I am indeed interested in just a string here. I updated my question to reflect this. How should I apply a `string-join()` here? Isn't that applied into a `value-of` as well? – Jessica_the_owl Sep 09 '19 at 17:18
  • 1
    Once you've got the string (using `string-join()`) you can put it into a text node using `xsl:value-of`, or into an attribute using `xsl:attribute` (or an AVT), or into a variable using `xsl:variable`, or return it from a function using `xsl:sequence`, etc. What I'm saying is, only use `xsl:value-of` if you actually want a text node. – Michael Kay Sep 09 '19 at 21:40
  • Thank you for your explanation, it makes sense now! – Jessica_the_owl Sep 10 '19 at 07:14
  • I decided to accept this as the answer, as it made me look into XSLT 3.0 features (http://dh.obdurodon.org/xslt3.xhtml). The introduction of the bang and arrow operators makes things more readable (in my opinion, of course). Also, text expansion is quite nice (`{name}` instead of ``), although I believe that cannot be applied here. – Jessica_the_owl Sep 10 '19 at 07:17