3

in one of our requirement we are receiving a string of n character and at provider at we we sending that to SAP. Due to some limitation at target end, we need to check for string that if its more then 100 char, we need to split that and send to target application in 2 different segment(same name) like

input - This is a test message......(till 150 char)

in XSLT transformation -we need to split it like

<text>first 100 char<text>
<text> 101 to 200 char<text>
...

Since number of character is not predefined so I cant use substring function here. This should be as a part of loop..

Could someone pls help here.

Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
kumarb
  • 521
  • 1
  • 7
  • 23
  • Can you use XSLT 2.0? – michael.hor257k Dec 03 '15 at 15:12
  • I dont think so.. since I have to change existing XSL where it says like ... so I guess we are on 1.0 version – kumarb Dec 03 '15 at 15:26
  • That's the XML version, not the XSLT version. – Michael Kay Dec 03 '15 at 15:28
  • @kumarb No, that doesn't mean anything. The real question is which processor are you using (or will be using in actual production). If you don't know, see how to find out here: http://stackoverflow.com/questions/25244370/how-can-i-check-which-xslt-processor-is-being-used-in-solr/25245033#25245033 – michael.hor257k Dec 03 '15 at 15:29
  • yes, my XSLT support 2.0 . Just checked. – kumarb Dec 03 '15 at 15:35
  • if possible suggest both options for 1.0 and 2.0 .. I see substring option but with that we should know that max string length.. here in my case it could be 1-3000 - so cant split that long. – kumarb Dec 03 '15 at 16:05

2 Answers2

4

In XSLT 2.0, you could do something like this:

Example simplified to splitting the input into tokens of (up to) 6 characters each.

XML

<input>abcde1abcde2abcde3abcde4abcde5abcde6abcde7abcde8abc</input>

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:template match="/">
     <output>
        <xsl:variable name="string" select="input" />
        <xsl:for-each select="0 to (string-length($string) - 1) idiv 6">
            <token>
                <xsl:value-of select="substring($string, . * 6 + 1, 6)" />
            </token>
        </xsl:for-each>
    </output>
</xsl:template>

</xsl:stylesheet>

Result

<output>
   <token>abcde1</token>
   <token>abcde2</token>
   <token>abcde3</token>
   <token>abcde4</token>
   <token>abcde5</token>
   <token>abcde6</token>
   <token>abcde7</token>
   <token>abcde8</token>
   <token>abc</token>
</output>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thanks, I see with XSLT 2.0 its working for me. However I am trying to understand what which specific function causing issue to run it on XSLT version 1.0. We are using same string functions here. – kumarb Dec 03 '15 at 17:13
  • if possible pls suggest for 1.0 version. Mean while I am trying to deploy my existing code by changing to version 2.0 - hopefully existing functions should not break – kumarb Dec 03 '15 at 17:32
  • @kumarb This cannot run in XSLT 1.0, because it does not have the `to` and `idiv` operators introduced in XPath 2.0. -- To do this in XSLT 1.0 requires a lot more work, which I will not do. – michael.hor257k Dec 03 '15 at 17:35
2

Here's an option for 1.0 (works in 2.0 too). It uses a recursive template call.

XML Input (Thanks Michael)

<input>abcde1abcde2abcde3abcde4abcde5abcde6abcde7abcde8abc</input>

XSLT 1.0

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

  <xsl:template match="/*">
    <output>
      <xsl:call-template name="tokenize">
        <xsl:with-param name="input" select="."/>
      </xsl:call-template>
    </output>
  </xsl:template>

  <xsl:template name="tokenize">
    <xsl:param name="input"/>
    <xsl:param name="length" select="6"/>
    <token><xsl:value-of select="substring($input,1,$length)"/></token>
    <xsl:if test="substring($input,$length+1)">
      <xsl:call-template name="tokenize">
        <xsl:with-param name="input" select="substring($input,$length+1)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

XML Output

<output>
   <token>abcde1</token>
   <token>abcde2</token>
   <token>abcde3</token>
   <token>abcde4</token>
   <token>abcde5</token>
   <token>abcde6</token>
   <token>abcde7</token>
   <token>abcde8</token>
   <token>abc</token>
</output>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95