-1

I have variable (array) - [123, 456, 789]. I need to extract all the values and output. I'm using XSLT 2.0.

Sample Input XML

<xsl:param name="pNumbers" select="'[123, 456, 789]'" />

<xsl:template match="Response">
    <xsl:copy-of select="."/>
      <xsl:element name="Numbers">
        <xsl:element name="Number">
              <xsl:value-of select="$pNumbers"/>
        </xsl:element>
      </xsl:element>
</xsl:template>

I need to get

           <Numbers>
                <Number>
                  123
              </Number>
                <Number>
                  456
              </Number>
                <Number>
                  789
              </Number>
          </Numbers>

Also, the value can be one in the array - [123]

       <Numbers>
            <Number>
              123
          </Number>
      </Numbers>

Using xsl:for-each did not happen to implement this.

Upd:

Almost, but not the last element

<xsl:template name="split">
   <xsl:param name="str" select="."/>
    <xsl:choose>
      <xsl:when test="contains($str, ',')">
        <xsl:element name="Number">
          <xsl:value-of select="normalize-space(substring-before($str, ','))"/>
        </xsl:element>
        <xsl:call-template name="split">
          <xsl:with-param name="str" select="substring-after($str, ',')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="Number">
            <xsl:value-of select="$pNumbers"/>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

Upd2

Solved XSLT 1.0. All thanks.

<xsl:template name="split">
     <xsl:param name="str" select="."/>
      <xsl:choose>
        <xsl:when test="contains($str, ',')">
          <xsl:element name="Number">
            <xsl:value-of select="normalize-space(substring-before($str, ','))"/>
          </xsl:element>
          <xsl:call-template name="split">
            <xsl:with-param name="str" select="substring-after($str, ',')"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="Number">
              <xsl:value-of select="normalize-space($str)"/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    <xsl:template match="Numbers">
                <xsl:element name="Number">
                                  <xsl:call-template name="split">
                <xsl:with-param name="str" select="substring-before(
                                                  substring-after(
                                                  $pNumber, '[' )
                                                  ,']' )" />
              </xsl:call-template>
            </xsl:element>
    </xsl:template>
11
  • XSLT dosn't have arrays unless you use XSLT 3.0 with XPath 3.1 support. And as your data comes from an extension function it is essencial anyway that you show and explain in detail which XSLT processor you use, how your extension function looks, in which language it is written. Commented May 23, 2017 at 10:05
  • We need to know what data type is your parameter. If it's a sequence, then you can do simply xsl:for-each to create an element for each value. If it's a string, tokenize it. Commented May 23, 2017 at 10:11
  • I'm trying something like this stackoverflow.com/questions/36176206/… Commented May 23, 2017 at 10:22
  • Please edit your question and show us exactly what you are doing, both in terms of XSLT as well as in terms of the XSLT processor, the programming language you write your extension function in, the API you use to call the extension function. Commented May 23, 2017 at 10:25
  • 1
    I am afraid <xsl:param name="pNumbers" select="["123", "456", "789"]" /> is not even well-formed XML so we still do not know what kind of input data you have. Commented May 23, 2017 at 10:51

1 Answer 1

1

If - as it seems - your parameter is a string, you need to tokenize it. In XSLT 2.0, this can be much simpler than what you have started to do:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="pNumbers" select="'[123, 456, 789]'" />

<xsl:template match="/">
    <Numbers>
        <xsl:for-each select="tokenize(substring($pNumbers, 2, string-length($pNumbers) - 2), ', ')">
            <Number>
                <xsl:value-of select="."/>
            </Number>
        </xsl:for-each>
    </Numbers>
</xsl:template>

</xsl:stylesheet>

Result

<Numbers>
   <Number>123</Number>
   <Number>456</Number>
   <Number>789</Number>
</Numbers>

If you have control over the parameter's format, then remove the surrounding square brackets. Then it will become even simpler.

Sign up to request clarification or add additional context in comments.

4 Comments

That's great! oh, it works everywhere, except IBM :(. Thanks. How is the same done on XSLT 1.0? Suddenly, the IBM gives a cropped XSLT 2.0 and something strange happens....
I am afraid I have no idea what "IBM gives a cropped XSLT 2.0" means. Are you using IBM DataPower as your XSLT processor? If yes, why are you asking about XSLT 2.0?
yes, IBM DataPower. Should have been 2.0, but apparently I was wrong. By your old answer, i made on 1.0, but the last value does not get
That's not my answer. And IBM Data Power is an XSLT 1.0 processor. However, AFAIK it supports the EXSLT str:tokenize() extension function. If you want to do this without extensions, then try this as the example: stackoverflow.com/a/23614821/3016153

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.