I have a XML like this:
<process id="Process_1">
<exclusiveGateway id="ExclusiveGateway_03b639w" />
<startEvent id="StartEvent_0nmzsw0" />
<sendTask id="Task_13s9uob"/>
<userTask id="Task_1v0riz3" />
</process>
I need to convert it to this with xslt:
<process id="Process_1">
<Gateway type="exclusive" id="ExclusiveGateway_03b639w" />
<Event type="start" id="StartEvent_0nmzsw0" />
<Task type="send" id="Task_13s9uob"/>
<Task type="user" id="Task_1v0riz3" />
</process>
I think I can use tokenize
function for this but I do not know how to separate tokens.
It would be very helpful if someone could explain solution for this problem.
Thanks.
To do this in XSLT 1.0, try something along the lines of:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/process/*">
<xsl:variable name="split" select="string-length(substring-before(translate(name(), 'BCDEFGHIJKLMNOPQRSTUVWXYZ', 'AAAAAAAAAAAAAAAAAAAAAAAAA'), 'A'))" />
<xsl:element name="{substring(name(), $split + 1)}">
<xsl:attribute name="type">
<xsl:value-of select="substring(name(), 1, $split)"/>
</xsl:attribute>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note that this assumes that all (and only) children of the root process
element need to be processed as shown.
P.S. If you know the structure of the input XML, it would be more robust to transform the individual elements explicitly, e.g.:
<xsl:template match="exclusiveGateway">
<Gateway type="exclusive">
<xsl:apply-templates select="@* | node()"/>
</Gateway>
</xsl:template>
Assuming the use of an XSLT 2.0 processor like Saxon 9 you can use
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[matches(local-name(), '^\p{Ll}+\p{Lu}')]">
<xsl:element name="{replace(local-name(), '^\p{Ll}+', '')}">
<xsl:attribute name="type" select="replace(local-name(), '\p{Lu}.*', '')"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Online at http://xsltransform.net/jz1PuNM.