2

I have an array of strings in .xsl file, now I have to use the each string separeted by spaces differently. How I can get the strings?

I have following array of strings:

strarray="hw.oh.xml hg.hd.gnl th.ik.lkj"

I have to get "hw.oh.xml" , "hg.hd.gnl" , "th.ik.lkj" strings separetaly to perform some operation on it.

How I can do that?

3
  • Good question, +1. See my answer for three complete solutions. :) Commented May 10, 2011 at 5:36
  • Wonderful...Very much thanks @ Dimitre Novatchev for your answers. But in my case i have the variable which contains is like as i shown in my problem. then how to handle it. and it contains more that 10 strings. Thanks in advance.. n im using version="1.0" of xslt. Commented May 10, 2011 at 5:56
  • You are welcome. Especially or your case I have added a fourth solution to my answer. Commented May 10, 2011 at 13:10

1 Answer 1

4

There are many ways to do this:

I. Using the XPath substring-before() and substring-after() functions:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vStrArray" select="'hw.oh.xml hg.hd.gnl th.ik.lkj'"/>

 <xsl:template match="/">
  <xsl:value-of select="substring-before($vStrArray, ' ')"/>
  <xsl:text>&#xA;</xsl:text>

  <xsl:value-of select="substring-before(substring-after($vStrArray, ' '),' ')"/>
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="substring-after(substring-after($vStrArray, ' '),' ')"/>
  <xsl:text>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on any XML document (not used), the wanted result (each item from the "array") is produced:

hw.oh.xml
hg.hd.gnl
th.ik.lkj

This method can quickly become overwhelmingly complex and is not recommended except for "arrays" of just 2-3 items.

II. Representing the "array" as an XML document in XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:array>
  <item>hw.oh.xml</item>
  <item>hg.hd.gnl</item>
  <item>th.ik.lkj</item>
 </my:array>

 <xsl:variable name="vStrArray"
      select="document('')/*/my:array/*"/>

 <xsl:template match="/">
  <xsl:value-of select="$vStrArray[1]"/>
  <xsl:text>&#xA;</xsl:text>

  <xsl:value-of select="$vStrArray[2]"/>
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="$vStrArray[3]"/>
  <xsl:text>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the same XML document (any), the wanted correct result is produced:

hw.oh.xml
hg.hd.gnl
th.ik.lkj

I recommend this method of representing an "array" -- for XSLT 1.0 applications.

III. XSLT 2.0 / XPath 2.0

Simply use a sequence of strings:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vStrArray"
      select="'hw.oh.xml', 'hg.hd.gnl', 'th.ik.lkj'"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "for $i in 1 to count($vStrArray)
     return
        concat($vStrArray[$i], '&#xA;')
   "/>
 </xsl:template>
</xsl:stylesheet>

Result:

 hw.oh.xml
 hg.hd.gnl
 th.ik.lkj

UPDATE: The OP commented that he is stuck with the initial representation of space-separated values, contained in a single string.

IV. Convert the space-separated values string into an XML fragment for easy use.

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vStrArray" select="'hw.oh.xml hg.hd.gnl th.ik.lkj'"/>

    <xsl:variable name="vrtfDoc">
      <xsl:call-template name="makeIndex">
        <xsl:with-param name="pText" select="$vStrArray"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="vStrIndex" select="ext:node-set($vrtfDoc)/*"/>

    <xsl:template match="/">
        <xsl:value-of select="$vStrIndex[1]"/>
        <xsl:text>&#xA;</xsl:text>
        <xsl:value-of select="$vStrIndex[2]"/>
        <xsl:text>&#xA;</xsl:text>
        <xsl:value-of select="$vStrIndex[3]"/>
    </xsl:template>

  <xsl:template name="makeIndex">
     <xsl:param name="pText"/>

     <xsl:if test="string-length($pText)>0">
      <item>
       <xsl:value-of select=
         "substring-before(concat($pText,' '), ' ')"/>
      </item>
      <xsl:call-template name="makeIndex">
       <xsl:with-param name="pText" select=
       "substring-after($pText,' ')"/>
      </xsl:call-template>
     </xsl:if>
    </xsl:template>
</xsl:stylesheet>

This transformation creates an XML fragment from the string in which every <item> element contains just one of the string values. Then its use is just as if it were an array.

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

Comments

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.