Reputation: 17
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
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
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
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
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