Manisha
Manisha

Reputation: 17

Element need to split into two elements in xsl

I have element

<PredecessorActivityUID>000005001302-0030</PredecessorActivityUID>`

in XSLT 2.0 I need to split it into two elements as

<PredecessorActivityUID1>000005001302</PredecessorActivityUID1>
<PredecessorActivityUID2>0030</PredecessorActivityUID1>

into two different variables PredecessorActivityUID1,PredecessorActivityUID2

Upvotes: 0

Views: 1084

Answers (4)

Daniel Haley
Daniel Haley

Reputation: 52858

I'd recommend tokenize()...

XML Input

<doc>
    <PredecessorActivityUID>000005001302-0030</PredecessorActivityUID>    
</doc>

XSLT 2.0

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="PredecessorActivityUID">
        <xsl:for-each select="tokenize(normalize-space(),'-')">
            <xsl:element name="PredecessorActivityUID{position()}">
                <xsl:value-of select="."/>
            </xsl:element>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Output

<doc>
   <PredecessorActivityUID1>000005001302</PredecessorActivityUID1>
   <PredecessorActivityUID2>0030</PredecessorActivityUID2>
</doc>

Upvotes: 1

Dan Field
Dan Field

Reputation: 21641

On this document:

<PredecessorActivityUID>000005001302-0030</PredecessorActivityUID>

Use this stylesheet:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/PredecessorActivityUID">
    <root>
      <xsl:variable name='uid1' select="substring-before(./text(), '-')"/>
      <xsl:variable name='uid2' select="substring-after(./text(), '-')"/>
      <PredecessorActivityUID1><xsl:value-of select='$uid1'/></PredecessorActivityUID1>
      <PredecessorActivityUID2><xsl:value-of select='$uid2'/></PredecessorActivityUID2>
    </root>
    </xsl:template>


</xsl:transform>

To get this result:

<root>
   <PredecessorActivityUID1>000005001302</PredecessorActivityUID1>
   <PredecessorActivityUID2>0030</PredecessorActivityUID2>
</root>

http://xsltransform.net/bdxtqn

You don't necessarily need a recursive template here, especially for such a simple requirement. That would be good if you had to split the string into more than one piece. tokenize() is great and would be supported by your processor, but your requirement is so simple that this code may be clearer (using a RegEx may be overkill for maintainability here).

This will work on XSLT 1.0 or 2.0, and shouldn't require any extensions or special processor-specific functions. You'll get the first part of the string in the variable $uid1 and the second part in the variable $uid2. You may not need those in variables (you could just replace the select from the variable in the select of the corresponding xsl:value-of if you don't need to use the values more than once or for other processing directives).

Upvotes: 1

leu
leu

Reputation: 2081

since you are using an XSLT 2.0 processor, I'd recommend to have a look at regular expressions which I think are one of the great advantages of 2.0 over 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:output indent="yes" method="xml"/>
  <xsl:template match="PredecessorActivityUID">
    <root>
      <PredecessorActivityUID1><xsl:value-of select="replace(.,'(^[^-]*)-(.*)','$1')"/></PredecessorActivityUID1>
      <PredecessorActivityUID2><xsl:value-of select="replace(.,'(^[^-]*)-(.*)','$2')"/></PredecessorActivityUID2>
    </root>
  </xsl:template>

</xsl:stylesheet>

One does not need them here, but it's good to know them.

Upvotes: 1

Rajesh
Rajesh

Reputation: 384

I just tried with substring funtion. See if it's useful.

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

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" />
  </xsl:copy>
 </xsl:template>

 <xsl:template match="PredecessorActivityUID" name="split">
  <xsl:param name="pText" select="." />

  <xsl:if test="$pText">
   <PredecessorActivityUID>
    <xsl:value-of select="substring-before(concat($pText, '-'), '-')" />
   </PredecessorActivityUID>

   <xsl:call-template name="split">
    <xsl:with-param name="pText" select="substring-after($pText, '-')" />
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions