Re: [xsl] Split one line to multiple lines

Subject: Re: [xsl] Split one line to multiple lines
From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 14 Oct 2014 14:10:19 -0000
Sudeshna,

Um, so, something like this.

<xsl:template match="Line">
    <xsl:call-template name="make-lines"/>
  </xsl:template>

 <xsl:template name="make-lines">
    <xsl:param name="line" select="."/>
    <xsl:param name="product-str" select="string(Product)"/>
    <xsl:variable name="prd" select="substring-before($product-str,';')"/>
    <xsl:choose>
      <xsl:when test="contains($product-str,';')">
        <Line>
          <xsl:copy-of select="$line/LineId"/>
          <Product>
            <xsl:value-of select="$prd"/>
          </Product>
          <xsl:copy-of select="$line/Amount"/>
        </Line>
        <xsl:call-template name="make-lines">
          <xsl:with-param name="line" select="$line"/>
          <xsl:with-param name="product-str"
select="substring-after($product-str,concat($prd,';'))"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="prd" select="$product-str"/>
        <xsl:if test="normalize-space($prd)">
        <Line>
          <xsl:copy-of select="$line/LineId"/>
          <Product>
            <xsl:value-of select="$prd"/>
          </Product>
          <xsl:copy-of select="$line/Amount"/>
        </Line>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

No pipelining is necessary here.

I apologize if I sounded cross earlier. I do wish, however, that
XSL-List were a bit more reflective and less of a "code-writing
service". Earlier in this thread Graydon provided you - freely
offering his service - a perfectly elegant solution and only when you
came back and said "XSLT 1.0 only" was it even clear what the problem
actually was. :-(

XSLT 1.0 is definitely in scope for this list, however (as I
understand it), and I don't wish to discourage questions about it.
They just need to be identified as such up front.

Cheers, Wendell



On Sat, Oct 11, 2014 at 1:53 PM, Wendell Piez wapiez@xxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
> Hi,
>
> Take a look at http://www.dpawson.co.uk/xsl/sect2/N7240.html
>
> Or read the section on string processing in Jeni Tennison's XSLT and
> XPath On the Edge (isbn 0764547763). If you are stuck with XSLT 1.0,
> this is an essential in your library.
>
> Generally speaking, in XSLT 1.0 one can process a string as a
> parameter through a recursive template, which works by "chopping" the
> string until it's gone.
>
> Partly it's cumbersome because you are limited to just a few
> string-manipulation functions. You have to operate on the strings
> using substring-before(), starts-with() and a few others.
>
> Since, in XSLT 1.0, one cannot pipeline (unless one can, because
> making result trees readable is a common extension in 1.0 processors),
> this is especially difficult to demonstrate. A decent solution must
> also be highly tuned to your own specific and particular requirements.
> It is also likely to be relatively verbose, even for XSLT. Code like
> this makes many people impatient especially when they know it is not
> necessary.
>
> Arguably a better solution than pure XSLT 1.0 in one pass: hack the
> tags themselves by hand (Perl, sed, awk) as a pre-process.
>
> If you at least have a node-set() extension function, this is slightly
> less crazy in XSLT 1.0.
>
> Good luck, Wendell
>
>
>
>
>
>
>
> On Fri, Oct 10, 2014 at 11:06 PM, sudheshna iyer
> sudheshnaiyer@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> wrote:
>> I am using oracle bpel transformation and it doesn't support xslt2.0. Can I
>> have the solution in xslt 1.0?
>>
>> Thank you very much for your help.
>>
>>
>>
>>
>> On Thursday, October 9, 2014 5:02 PM, "sudheshna iyer
>> sudheshnaiyer@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>>
>>
>> Thank you very much, Graydon. Let me try that over.
>>
>>
>>
>>
>> On Thursday, October 9, 2014 4:23 PM, "Graydon graydon@xxxxxxxxx"
>> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>>
>>
>> On Thu, Oct 09, 2014 at 07:59:09PM -0000, sudheshna iyer
>> sudheshnaiyer@xxxxxxxxx scripsit:
>>> I want to split the values in "Product" to multiple lines. For eg: for
>>> LineId = 222, there are 3 values (BBB;CCC;DDD;). So I need to create 3 lines
>>> along with the first line. How can I do that?
>>> Eg:
>>> <ns1:Lines>
>>> <ns1:Line>
>>> <ns1:LineId>111</ns1:LineId>
>>> <ns1:Product>AA</ns1:Product>
>>> <ns1:Amount>100</ns1:Amount>
>>> </ns1:Line>
>>> <ns1:Line>
>>> <ns1:LineId>222</ns1:LineId>
>>> <ns1:Product>BBB;CCC;DDD;</ns1:Product>
>>> <ns1:Amount>200</ns1:Amount>
>>> </ns1:Line>
>>> </ns1:Lines>
>>>
>>> Output
>>> <ns1:Lines>
>>> <ns1:Line>
>>> <ns1:LineId>111</ns1:LineId>
>>> <ns1:Product>AAA</ns1:Product>
>>> <ns1:Amount>100</ns1:Amount>
>>> </ns1:Line>
>>> <ns1:Line>
>>> <ns1:LineId>222</ns1:LineId>
>>> <ns1:Product>BBB</ns1:Product>
>>> <ns1:Amount>100</ns1:Amount>
>>> </ns1:Line>
>>> <ns1:Line>
>>> <ns1:LineId>222</ns1:LineId>
>>> <ns1:Product>CCC</ns1:Product>
>>> <ns1:Amount>100</ns1:Amount>
>>> </ns1:Line>
>>> <ns1:Line>
>>> <ns1:LineId>222</ns1:LineId>
>>> <ns1:Product>DDD</ns1:Product>
>>> <ns1:Amount>100</ns1:Amount>
>>> </ns1:Line>
>>> </ns1:Lines>
>>>
>>> I know there is a tokenize function. But how do I copy other values?
>>
>> <xsl:template match="node()|@*">
>>     <xsl:copy>
>>         <xsl:apply-templates select="node()|@*" />
>>     </xsl:copy>
>> </xsl:template>
>>
>> <xsl:template match="ns1:Line">
>>     <xsl:variable name="original" select="." />
>>     <xsl:for-each
>> select="tokenize(normalize-space(ns1:Product),';\p{Zs}*')[normalize-space()]">
>>         <ns1:Line>
>>             <xsl:apply-templates select="$original/ns1:LineId" />
>>             <ns1:Product>
>>                 <xsl:value-of select="." />
>>             </ns1:Product>
>>             <xsl:apply-templates select="$original/ns1:Amount" />
>>         </ns1:Line>
>>     </xsl:for-each>
>> </xsl:template>
>>
>>
>> You notice that what you're doing is relative to the ns1:Line elements, and
>> that while you could select only those ns1:Line elements were you need to
>> split
>> things
>>
>> <xsl:template match="ns1:Line[matches(ns1:Product,';')]">
>>
>> you don't need to; tokenizing where there aren't any semi-colons just
>> returns
>> whatever was there.
>>
>> You watch out for the trailing semi-colons by excluding the null string from
>> the sequence produced by tokenize -- that's what [normalize-space()] does --
>> and you use a variable to hang on to the original element context, which you
>> lose inside the for-each.
>>
>> -- Graydon
>>
>>
>>
>> XSL-List info and archive
>> EasyUnsubscribe (by email)
>>
>>
>> XSL-List info and archive
>> EasyUnsubscribe (by email)
>
>
>
> --
> Wendell Piez | http://www.wendellpiez.com
> XML | XSLT | electronic publishing
> Eat Your Vegetables
> _____oo_________o_o___ooooo____ooooooo_^
> 



-- 
Wendell Piez | http://www.wendellpiez.com
XML | XSLT | electronic publishing
Eat Your Vegetables
_____oo_________o_o___ooooo____ooooooo_^

Current Thread