My source document is:
<?xml version="1.0" encoding="UTF8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:fn="http://www.w3.org/2005/xpathfunctions" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 schema\BPMN20.xsd" targetNamespace="http://schema.omg.org/spec/BPMN/2.0">
<process id="DA444C7EB7A92BC0EC615091EFE52E9F" name="Process111">
<laneSet>
<lane id="BE805267E22661E25210E901418B7DA2" name="Lane111" >
<flowNodeRefs>E705CE86B8897B266BA6AC81E2F1A5BC</flowNodeRefs>
<flowNodeRefs>643E3A26322BEECB2DBD84BF2A6F9CA5</flowNodeRefs>
</lane>
<lane id="2F92C8B27CE52AFDB382D4EAC634E634" name="Lane222" >
<flowNodeRefs>A65A0630689FA02F3BBB6AC27D906603</flowNodeRefs>
<flowNodeRefs>DDA49A7836C13B7DC3208778C4B03526</flowNodeRefs>
</lane>
</laneSet>
<startEvent id="E705CE86B8897B266BA6AC81E2F1A5BC" name="Start111" />
<endEvent id="643E3A26322BEECB2DBD84BF2A6F9CA5" name="End111" />
<startEvent id="A65A0630689FA02F3BBB6AC27D906603" name="Start222" />
<terminateEvent id="DDA49A7836C13B7DC3208778C4B03526" name="Terminate111" />
</process>
<process id="A7F84E7EA73F9436DCB925D5C3208227" name="Process2222">
<laneSet>
<lane id="B8EE1D7AA494C6D25656434F1CAF803F" name="Lane444" />
</laneSet>
</process>
</definitions>
I want to tranform to the target document:
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns.x="org.w3c.dom.svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<g id="BPMNDIAGRAM" transform="scale(1)">
<g id="POOLS" class="POOLS">
<g id="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F" class="POOL" >
<g >
<text >
<tspan >Process111</tspan>
</text>
</g>
<g id="BE805267-E226-61E2-5210-E901418B7DA2" class="LANE" PoolID="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F">
<g>
<text >
<tspan>Lane111</tspan>
</text>
</g>
<g id="EVENTS_BE805267-E226-61E2-5210-E901418B7DA2" class="EVENTS">
<g id="643E3A26-322B-EECB-2DBD-84BF2A6F9CA5" class="ENDEVENT" LaneID="BE805267-E226-61E2-5210-E901418B7DA2">
<text >
<tspan >End111</tspan>
</text>
</g>
<g id="E705CE86-B889-7B26-6BA6-AC81E2F1A5BC" class="STARTEVENT" LaneID="BE805267-E226-61E2-5210-E901418B7DA2">
<text >
<tspan x="0" dy="10">Start111</tspan>
</text>
</g>
</g>
</g>
<g id="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634" class="LANE" PoolID="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F">
<g >
<text >
<tspan x="0" dy="10">Lane222</tspan>
</text>
</g>
<g id="EVENTS_2F92C8B2-7CE5-2AFD-B382-D4EAC634E634" class="EVENTS">
<g id="A65A0630689FA02F3BBB6AC27D906603" class="STARTEVENT" LaneID="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634">
<text >
<tspan x="0" dy="10">Start222</tspan>
</text>
</g>
<g id="DDA49A78-36C1-3B7D-C320-8778C4B03526" class="TERMINATEEVENT" LaneID="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634">
<text >
<tspan x="0" dy="10">Terminate111</tspan>
</text>
</g>
</g>
</g>
</g>
<g id="A7F84E7E-A73F-9436-DCB9-25D5C3208227" class="POOL" >
<g >
<text >
<tspan >Process2222</tspan>
</text>
</g>
<g id="B8EE1D7A-A494-C6D2-5656-434F1CAF803F" class="LANE" PoolID="A7F84E7E-A73F-9436-DCB9-25D5C3208227">
<g >
<text >
<tspan>Lane444</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</svg>
And my transformation file is as following code:
<?xml version="1.0" encoding="Windows-1252"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- BPMN 2.0 Transformation: BPMN2.0 xml-to-SVG xml -->
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<svg>
<xsl:attribute name="xmlns.x">org.w3c.dom.svg</xsl:attribute>
<xsl:attribute name="targetNamespace">http://schema.omg.org/spec/BPMN/2.0</xsl:attribute>
<xsl:call-template name="rootElementTemplate"/>
</svg>
</xsl:template>
<!-- rootElementTemplate -->
<xsl:template name="rootElementTemplate">
<g>
<!--call the other templates-->
<xsl:call-template name="pools"/>
</g>
</xsl:template>
<xsl:template name="pools">
<g>
<xsl:attribute name="id">POOLS</xsl:attribute>
<xsl:attribute name="class">POOLS</xsl:attribute>
<xsl:apply-templates select="process"/>
</g>
</xsl:template>
<xsl:template match="process">
<g>
<xsl:attribute name="id"><xsl:value-of select="."/></xsl:attribute>
<xsl:attribute name="class">POOL</xsl:attribute>
<xsl:call-template name="text1"/>
</g>
</xsl:template>
<xsl:template name="text1" >
<xsl:for-each select="#name">
<g >
<xsl:element name="text">
<xsl:element name="tspan"><xsl:value-of select= "."/></xsl:element>
</xsl:element>
</g>
</xsl:for-each>
</xsl:template>
<xsl:template match="lane">
<g id="{#id}" class="LANE" >
<xsl:apply-templates select="#name"/>
<xsl:variable name="p" select="count(preceding-sibling::lane)+1"/>
<xsl:variable name="ref" select="ancestor::process/*[$p+1]"/>
<xsl:apply-templates select="$ref"/>
</g>
</xsl:template>
<xsl:template match="startevent">
<g id="{#id}" class="STARTEVENT" name="{#name}" />
</xsl:template>
</xsl:stylesheet>
I don't know why it doesn't work? Please help me
This stylesheet:
<xsl:stylesheet version="1.0"
exclude-result-prefixes="m"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:x="org.w3c.dom.svg">
<xsl:variable name="attrSet">
<dummy x="0" dy="10"/>
</xsl:variable>
<xsl:template match="m:definitions">
<svg version="1.1">
<g id="BPMNDIAGRAM" transform="scale(1)">
<g id="POOLS" class="POOLS">
<xsl:apply-templates />
</g>
</g>
</svg>
</xsl:template>
<xsl:template match="m:process">
<g class="POOL">
<xsl:apply-templates select="#id"/>
<xsl:apply-templates select="#name|m:laneSet/*"/>
</g>
</xsl:template>
<xsl:template match="*">
<xsl:param name="idName" select="'PoolID'"/>
<xsl:param name="id" select="../../#id"/>
<g class="{translate(name(),
'lanedvtsrmi',
'LANEDVTSRMI')}">
<xsl:attribute name="{$idName}">
<xsl:apply-templates select="$id" mode="id"/>
</xsl:attribute>
<xsl:apply-templates select="#id"/>
<xsl:apply-templates select="#name"/>
<xsl:apply-templates/>
</g>
</xsl:template>
<xsl:template match="m:flowNodeRefs[position()!=1]"/>
<xsl:template match="m:flowNodeRefs[1]">
<g class="EVENTS">
<xsl:attribute name="id">
<xsl:text>EVENTS_</xsl:text>
<xsl:apply-templates select="../#id" mode="id"/>
</xsl:attribute>
<xsl:apply-templates select="../../../*[#id = current()/../*]">
<xsl:with-param name="idName" select="'LaneID'"/>
<xsl:with-param name="id" select="../#id"/>
</xsl:apply-templates>
</g>
</xsl:template>
<xsl:template match="#id">
<xsl:attribute name="id">
<xsl:apply-templates select="." mode="id"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="#id" mode="id">
<xsl:value-of select="concat(substring(.,1,8),'-',
substring(.,9,4),'-',
substring(.,13,4),'-',
substring(.,17,4),'-',
substring(.,21))"/>
</xsl:template>
<xsl:template match="#name">
<g>
<text>
<tspan>
<xsl:copy-of select="document('')/*/xsl:variable
[#name='attrSet']/*/#*
[not(current()/../self::m:endEvent|
current()/../self::m:process)]
[not(generate-id(current()/..) =
generate-id(current()/../../m:lane[1]))]"/>
<xsl:value-of select="."/>
</tspan>
</text>
</g>
</xsl:template>
</xsl:stylesheet>
Output:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:x="org.w3c.dom.svg">
<g id="BPMNDIAGRAM" transform="scale(1)">
<g id="POOLS" class="POOLS">
<g class="POOL" id="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F">
<g>
<text>
<tspan>Process111</tspan>
</text>
</g>
<g class="LANE" PoolID="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F" id="BE805267-E226-61E2-5210-E901418B7DA2">
<g>
<text>
<tspan>Lane111</tspan>
</text>
</g>
<g class="EVENTS" id="EVENTS_BE805267-E226-61E2-5210-E901418B7DA2">
<g class="STARTEVENT" LaneID="BE805267-E226-61E2-5210-E901418B7DA2" id="E705CE86-B889-7B26-6BA6-AC81E2F1A5BC">
<g>
<text>
<tspan x="0" dy="10">Start111</tspan>
</text>
</g>
</g>
<g class="ENDEVENT" LaneID="BE805267-E226-61E2-5210-E901418B7DA2" id="643E3A26-322B-EECB-2DBD-84BF2A6F9CA5">
<g>
<text>
<tspan>End111</tspan>
</text>
</g>
</g>
</g>
</g>
<g class="LANE" PoolID="DA444C7E-B7A9-2BC0-EC61-5091EFE52E9F" id="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634">
<g>
<text>
<tspan x="0" dy="10">Lane222</tspan>
</text>
</g>
<g class="EVENTS" id="EVENTS_2F92C8B2-7CE5-2AFD-B382-D4EAC634E634">
<g class="STARTEVENT" LaneID="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634" id="A65A0630-689F-A02F-3BBB-6AC27D906603">
<g>
<text>
<tspan x="0" dy="10">Start222</tspan>
</text>
</g>
</g>
<g class="TERMINATEEVENT" LaneID="2F92C8B2-7CE5-2AFD-B382-D4EAC634E634" id="DDA49A78-36C1-3B7D-C320-8778C4B03526">
<g>
<text>
<tspan x="0" dy="10">Terminate111</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
<g class="POOL" id="A7F84E7E-A73F-9436-DCB9-25D5C3208227">
<g>
<text>
<tspan>Process2222</tspan>
</text>
</g>
<g class="LANE" PoolID="A7F84E7E-A73F-9436-DCB9-25D5C3208227" id="B8EE1D7A-A494-C6D2-5656-434F1CAF803F">
<g>
<text>
<tspan>Lane444</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</svg>
Note: These lines
<xsl:apply-templates select="#id"/>
<xsl:apply-templates select="#name|m:laneSet/*"/>
And
<xsl:apply-templates select="#id"/>
<xsl:apply-templates select="#name"/>
<xsl:apply-templates/>
Could be like
<xsl:apply-templates select="#*|m:laneSet/*"/>
And
<xsl:apply-templates select="#*|*"/>
But, there is no guarantee from the spec that attributes are proccess in any order (beside that before child elements).
Also, I use a tricky way for add x and dy attributes. But the conditions in predicates could be use as test for a xsl:if, adding these attributes with xsl:attribute.
Related
This XSLT transformation works, but I am repeating the same code multiple times, which makes it very redundant!
How can I optimize this?
<xsl:for-each select="RVWT">
<xsl:variable name="rvwt" select="tokenize(., '\|')"/>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">
<xsl:value-of select="$rvwt[1]"/>
</Text>
<TextSourceTitle>
<xsl:value-of select="normalize-space(substring($rvwt[2], 3))"/>
</TextSourceTitle>
</xsl:for-each>
<xsl:if test="not(RVWT)">
<xsl:for-each select="RVW">
<xsl:variable name="rvwt" select="tokenize(., '\|')"/>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">
<xsl:value-of select="$rvwt[1]"/>
</Text>
<TextSourceTitle>
<xsl:value-of select="normalize-space(substring($rvwt[2], 3))"/>
</TextSourceTitle>
</xsl:for-each>
</xsl:if>
Thanks!
I. I would use the best that XSLT 2.0 can offer: creating a function:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:sequence select=
"my:Extract(RVW[not(../RVWT)] | RVWT)"/>
</xsl:template>
<xsl:function name="my:Extract">
<xsl:param name="pItems" as="item()+"/>
<xsl:for-each select="$pItems">
<xsl:variable name="vItemTokens" select="tokenize(., '\|')"/>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">
<xsl:value-of select="$vItemTokens[1]"/>
</Text>
<TextSourceTitle>
<xsl:value-of select="normalize-space(substring($vItemTokens[2], 3))"/>
</TextSourceTitle>
</xsl:for-each>
</xsl:function>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t>
<RVWT>a|bbbTail|c</RVWT>
<RVWT>d|eeeTail|f</RVWT>
<RVWT>g|hhhTail|i</RVWT>
<RVW>p|qqqTail|r</RVW>
</t>
the wanted, correct result is produced:
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">a</Text>
<TextSourceTitle>bTail</TextSourceTitle>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">d</Text>
<TextSourceTitle>eTail</TextSourceTitle>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">g</Text>
<TextSourceTitle>hTail</TextSourceTitle>
when applied on this document:
<t>
<RVWTX>a|bbbTail|c</RVWTX>
<RVWTX>d|eeeTail|f</RVWTX>
<RVWTX>g|hhhTail|i</RVWTX>
<RVW>p|qqqTail|r</RVW>
</t>
again the wanted, correct result is produced:
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">p</Text>
<TextSourceTitle>qTail</TextSourceTitle>
II. Do note:
With this approach we have the added benefit that the function accepts any sequence of items, not only elements.
For example, one could call the function like this:
my:Extract(('a|bbbTail|c', 'd|eeeTail|f'))
and still get the wanted result:
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">a</Text>
<TextSourceTitle>bTail</TextSourceTitle>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">d</Text>
<TextSourceTitle>eTail</TextSourceTitle>
You can write a template
<xsl:template match="RVWT | RVW">
<xsl:variable name="rvwt" select="tokenize(., '\|')"/>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">
<xsl:value-of select="$rvwt[1]"/>
</Text>
<TextSourceTitle>
<xsl:value-of select="normalize-space(substring($rvwt[2], 3))"/>
</TextSourceTitle>
</xsl:template>
and then in the parent you process <xsl:apply-templates select="if (RVWT) then RVWT else RVW"/>.
I am guessing you could do:
<xsl:for-each select="RVWT | RVW[not(../RVWT)]">
<xsl:variable name="rvwt" select="tokenize(., '\|')"/>
<TextTypeCode>08</TextTypeCode>
<Text textformat="05">
<xsl:value-of select="$rvwt[1]"/>
</Text>
<TextSourceTitle>
<xsl:value-of select="normalize-space(substring($rvwt[2], 3))"/>
</TextSourceTitle>
</xsl:for-each>
Iam trying to transform a reference xml to other dtd specific
Input:
<ref>
<a>text</a>
<b>text</b>
<c>text</c>
<d>text</d>
</ref>
XSLT:
<xsl:template match="ref">
<ref>
<h>
<xsl:apply-templates select="./a"/>
</h>
<g>
<xsl:apply-templates />
</g>
</ref>
</xsl:template>
<xsl:template match="ref/a">
<a>
<xsl:apply-templates />
</a>
</xsl:template>
Output derived:
<ref>
<h>
<a>text</a>
</h>
<g>
<a>text</a>
<b>text</b>
<c>text</c>
<d>text</d>
</g>
</ref>
Desired output:
<ref>
<h>
<a>text</a>
</h>
<g>
<b>text</b>
<c>text</c>
<d>text</d>
</g>
</ref>
Should i be using mode to do this or should be calling template for, if so how to do it.
I suspect this is more what you want to do:
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ref">
<ref>
<h>
<xsl:apply-templates select="./*[1]"/>
</h>
<g>
<xsl:apply-templates select="./*[generate-id() != generate-id(../*[1])]"/>
</g>
</ref>
</xsl:template>
<xsl:template match="ref/*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
Instead of
<g>
<xsl:apply-templates />
</g>
use
<g>
<xsl:apply-templates select="node() except a"/>
</g>
in XSLT 2.0
Finally used 'mode' to get it done.
<xsl:template match="ref">
<ref>
<h>
<xsl:apply-templates select="./a" mode="add"/>
</h>
<g>
<xsl:apply-templates />
</g>
</ref>
</xsl:template>
<xsl:template match="ref/a"/>
<xsl:template match="ref/a" mode="add">
<a>
<xsl:apply-templates />
</a>
</xsl:template>
I am trying to wrap all the text node in a <text> element, but facing challenge when encounter an inline elements (i, b, emphasis), that should be in same <text> node (in other words, it should be considered as text)... Please see input and desired output below:
(Note: I have to do this for specific inline elements only, hence kept it in param (it could be anything), for rest of the elements standard <text> rule should be applied. (Please see my xslt for details)
Input XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<para>XML Translation is a format that's used to <emphasis>exchange <i>localisation</i></emphasis>data</para>
<para>The process can now be reformulated with more detail as follows:<ul>
<li>Text extraction <note>Separation of translatable text from layout data</note></li>
<li>Pre-translation</li>
<li>Translation</li>
<li>Reverse conversion</li>
<li>Translation memory improvement</li>
</ul>above mentioned steps should <b>executed</b> sequentially</para>
</root>
OutPut should be:
<?xml version="1.0" encoding="utf-8"?>
<root>
<para>
<text xid="d0t3">XML Translation is a format that's used to <g ctype="emphasis">exchange <g ctype="i">localisation</g></g>data </text>
</para>
<para>
<text xid="d0t10">The process can now be reformulated with more detail as follows:</text>
<ul>
<li><text xid="d0t13">Text extraction <g ctype="note">Separation of translatable text from layout data</g></text></li>
<li><text xid="d0t17">Pre-translation</text></li>
<li><text xid="d0t19">Translation</text></li>
<li><text xid="d0t21">Reverse conversion</text></li>
<li><text xid="d0t23">Translation memory improvement</text></li>
</ul>
<text xid="d0t24">above mentioned steps should <g ctype="b">executed</g> sequentially</text>
</para>
</root>
I am trying something like this, but not able to achieve correct result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:param name="inlineElement" select="('emphasis', 'i', 'note', 'b')"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<text>
<xsl:attribute name="xid">
<xsl:value-of select="generate-id()"/>
</xsl:attribute>
<xsl:value-of select="."/>
<xsl:if test="following-sibling::node()[local-name()=$inlineElement]">
<g>
<xsl:apply-templates select="following-sibling::node()[local-name()=$inlineElement]/text()"/>
</g>
</xsl:if>
</text>
</xsl:template>
</xsl:stylesheet>
I would use for-each-group group-adjacent:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:param name="inlineElement" select="('emphasis', 'i', 'note', 'b')"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(local-name() = $inlineElement)]">
<xsl:copy>
<xsl:for-each-group select="node()" group-adjacent="boolean(self::text() | self::*[local-name() = $inlineElement])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<text xid="{generate-id(current-group()[self::text()][1])}">
<xsl:apply-templates select="current-group()"/>
</text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name() = $inlineElement]">
<g ctype="{local-name()}">
<xsl:apply-templates/>
</g>
</xsl:template>
</xsl:stylesheet>
That way, with Saxon 9.5, I get
<?xml version="1.0" encoding="UTF-8"?>
<root>
<para>
<text xid="d1t3">XML Translation is a format that's used to <g ctype="emphasis">exchange <g ctype="i">localisation</g>
</g>data</text>
</para>
<para>
<text xid="d1t10">The process can now be reformulated with more detail as follows:</text>
<ul>
<li>
<text xid="d1t13">Text extraction <g ctype="note">Separation of translatable text from layout data</g>
</text>
</li>
<li>
<text xid="d1t17">Pre-translation</text>
</li>
<li>
<text xid="d1t19">Translation</text>
</li>
<li>
<text xid="d1t21">Reverse conversion</text>
</li>
<li>
<text xid="d1t23">Translation memory improvement</text>
</li>
</ul>
<text xid="d1t24">above mentioned steps should <g ctype="b">executed</g> sequentially</text>
</para>
</root>
I have the following input XML file:
<root>
<a>
<b>1</b>
</a>
<c>
<d>
<e>2</e>
<f>3</f> or <e>3</e>
</d>
<g h="4"/>
<i>
<j>
<k>
<l m="5" n="6" o="7" />
<l m="8" n="9" o="0" />
</k>
</j>
</i>
</c>
</root>
I would like to use XSLT to transform it into the follow outputs:
OUTPUT 1
<root>
<row b="1" e="2" f="3" h="4" m="5" n="6" o="7" />
<row b="1" e="2" f="3" h="4" m="8" n="9" o="0" />
<root>
OUTPUT 2
<root>
<row b="1" e="2" h="4" m="5" n="6" o="7" />
<row b="1" e="2" h="4" m="8" n="9" o="0" />
<row b="1" e="3" h="4" m="5" n="6" o="7" />
<row b="1" e="3" h="4" m="8" n="9" o="0" />
<root>
Can anyone help my XSLT isn't very strong. Thanks.
It will be easier if you let the occurrence of <e> determine the outer loop constructing your <row>s and have a inner loop iterating over all <l>s.
Try something like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="root">
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<xsl:template match="e">
<!-- store values of 'e' and 'f' in params -->
<xsl:param name="value_of_e" select="." />
<xsl:param name="value_of_f" select="ancestor::d[1]/f" />
<!-- iterate over all 'l's -->
<xsl:for-each select="//l">
<xsl:element name="row">
<xsl:attribute name="b">
<xsl:value-of select="//b" />
</xsl:attribute>
<xsl:attribute name="e">
<xsl:value-of select="$value_of_e" />
</xsl:attribute>
<!-- only include 'f' if it has a value -->
<xsl:if test="$value_of_f != ''">
<xsl:attribute name="f">
<xsl:value-of select="$value_of_f" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="h">
<xsl:value-of select="ancestor::c[1]/g/#h" />
</xsl:attribute>
<xsl:attribute name="m">
<xsl:value-of select="./#m" />
</xsl:attribute>
<xsl:attribute name="n">
<xsl:value-of select="./#n" />
</xsl:attribute>
<xsl:attribute name="o">
<xsl:value-of select="./#o" />
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template match="b" />
<xsl:template match="f" />
<xsl:template match="g" />
</xsl:stylesheet>
I have the XML source file in SVG present like this:
<svg>
<g id='a001' class='pools'>
<g id='b001' class='pool' name='Proc111'>
<g id='c001' class='lane' name='User111' PoolID='b001'>
<g id='d001' class='startevent' name='startevent111' LaneID='c001'></g>
</g>
<g id='c002' class='lane' name='User222' PoolID='b001'>
<g id='d002' class='gateway' name='gateway111' LaneID='c002'></g>
</g>
</g>
<g id='b002' class='pool' name='Proc222'>
<g id='c003' class='lane' name=' customer ' PoolID=' b002'>
<g id='d003' class='endevent' name='endevent111' LaneID='c003'> </g>
</g>
</g>
</g>
<g id='a002' class='messageflows'/>
</svg>
i wanna tranform to XML target as following document:
<process id='a001' name='proc111'>
<laneset>
<lane name='User111'/>
<lane name='User222'/>
</laneset>
<startevent id='d001' name='startevent111'/>
<gateway id='d002' name='gateway111'/>
</process>
<process id='a002' name='proc222'>
<laneset>
<lane name='customer'/>
</laneset>
<endevent id='d003' name='endevent111'/>
</process>
I had tried with some transformation but it was unsuccessfull...My solution is create the main template; and inside the main template(process template), I call for the other templates which are starteventtemplate, endeventtemplate, gateway template, etc. However, in the target document, I get all childrent which are present the same for each parent elements('process').
Because the real file is bigger than this example with a lot of elements...So, I've carried out the main problem to apply for the remaining elements.
Using the following stylesheet you can generate the desired output:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<processes>
<xsl:apply-templates />
</processes>
</xsl:template>
<xsl:template match="g[#class='pool']" >
<process>
<laneset>
<xsl:apply-templates mode="laneset" />
</laneset>
<xsl:apply-templates mode="startevent" />
<xsl:apply-templates mode="gateway" />
</process>
</xsl:template>
<xsl:template match="g[#class='lane']" mode="laneset">
<lane name="{#name}"/>
</xsl:template>
<xsl:template match="g[#class='startevent']" mode="startevent">
<startevent id="{#id}" name="{#name}"/>
</xsl:template>
<xsl:template match="g[#class='gateway']" mode="gateway">
<gateway id="{#id}" name="{#name}"/>
</xsl:template>
</xsl:stylesheet>
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="g[#class='pools']">
<processes>
<xsl:apply-templates />
</processes>
</xsl:template>
<xsl:template match="g[#class='pool']" priority="1">
<process id="{#id}" name="{#name}">
<laneset>
<xsl:apply-templates/>
</laneset>
<xsl:apply-templates select="*/*"/>
</process>
</xsl:template>
<xsl:template match="g/g">
<xsl:element name="{#class}">
<xsl:copy-of select="#id[../#class != 'lane']|#name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<processes>
<process id="b001" name="Proc111">
<laneset>
<lane name="User111" />
<lane name="User222" />
</laneset>
<startevent id="d001" name="startevent111" />
<gateway id="d002" name="gateway111" />
</process>
<process id="b002" name="Proc222">
<laneset>
<lane name=" customer " />
</laneset>
<endevent id="d003" name="endevent111" />
</process>
</processes>
EDIT: compacting code.