xsl-list
[Top] [All Lists]

Re: [xsl] Split one line to multiple lines

2014-10-09 15:22:51
On Thu, Oct 09, 2014 at 07:59:09PM -0000, sudheshna iyer 
sudheshnaiyer(_at_)yahoo(_dot_)com 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: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>