merging distinct valued nodes in a node stream using xsl - xslt

I want to merge distinct valued nodes from a list of nodes using xsl. Whenever distinct value violets it creates a new tag.
Input:
<PAGE>
<T>1</T>
<T>2</T>
<T>3</T>
<T>2</T>
<T>1</T>
<T>3</T>
<T>3</T>
</PAGE>
Output:
<PAGE>
<T>1,2,3</T>
<T>2,1,3</T>
<T>3</T>
</PAGE>
Suppose first three nodes are having value 1,2 and 3 and the the fourth node is having value 2, then we have to merge first three as all values are unique. Then next merging will start from fourth node. Now suppose fifth node is again having value 2. Then in out only fourth node will be there as the next node value is same. Like wise I have to keep on merging nodes as long as the values are unique. For example if the node value stream is 1,2,2,3,4,1,1,3,3, the the Output will be 12,2341,13,3.IN merged node unique values can exist.
Please suggest me a XSL to do that

The following stylesheet:
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="*"/>
<xsl:template match="PAGE">
<xsl:copy>
<xsl:apply-templates select="T[1]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="T">
<xsl:param name="prev-string" select="','"/>
<xsl:variable name="next-string" select="concat($prev-string, ., ',')" />
<xsl:variable name="next-node" select="following-sibling::T[1]" />
<xsl:choose>
<xsl:when test="contains($next-string, concat(',', $next-node, ',')) or not($next-node)">
<!-- End of chain: create an element and output the accumulated string ... -->
<xsl:copy>
<xsl:value-of select="substring($next-string, 2, string-length($next-string) - 2)"/>
</xsl:copy>
<!-- ... and start a new chain -->
<xsl:apply-templates select="$next-node"/>
</xsl:when>
<xsl:otherwise>
<!-- Continue the current chain: add the current value to the accumulated values -->
<xsl:apply-templates select="$next-node">
<xsl:with-param name="prev-string" select="$next-string"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when applied to your example input, will return:
<?xml version="1.0" encoding="UTF-8"?>
<PAGE>
<T>1,2,3</T>
<T>2,1,3</T>
<T>3</T>
</PAGE>
Note:
It is assumed that values do not contain the separating character
(comma in this example);
Although this employs tail-recursion (partially, anyway), a large document could easily send your processor into stack overflow.

Related

using set:intersection in XSLT

I am trying to use tokenize with intersection from exslt in XALAN.
Sample Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets" xmlns:str="http://exslt.org/strings"
>
<xsl:template match="/">
Number of Values in Var1: <xsl:value-of select="count(str:tokenize(ROOT/Var1,'|'))" />
Number of Values in Var2: <xsl:value-of select="count(str:tokenize(ROOT/Var2,'|'))" />
Common Values: <xsl:value-of select="count(set:intersection(str:tokenize(ROOT/Var1,'|'),str:tokenize(ROOT/Var2,'|')))" />
</xsl:template>
</xsl:stylesheet>
Here is sample Input:
<ROOT>
<Var1>Hello|One|Two</Var1>
<Var2>Hello|One|Two|Three</Var2>
</ROOT>
I would expect intersection to report value of 3 - but it is always reporting 0.
My current output:
<?xml version="1.0" encoding="UTF-8"?>
Number of Values in Var1: 3
Number of Values in Var2: 4
Common Values: 0
Is there something incorrect in approach?
Yes the two calls to str:tokenize yield two distinct sets of token elements. None of the nodes in the first set are present in the second set. The two nodesets contain element nodes some of which have the same name and textual content as nodes in the other set, but in each such case these are pairs of nodes which have the same properties, but not the same node.
What you need is to define an intersection based on textual equality rather than node identity.
You could try something like this:
<xsl:variable name="set1" select="str:tokenize(ROOT/Var1,'|')"/>
<xsl:variable name="set2" select="str:tokenize(ROOT/Var2,'|')"/>
<xsl:variable name="intersection" select="$set1[.=$set2]"/>
This will return the set of nodes from $set1 which are textually equal to a node in $set2.
Here is final solution, with Conal's solution example:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets" xmlns:str="http://exslt.org/strings" xmlns:common="http://exslt.org/common"
>
<xsl:template match="/">
Number of Values in Var1: <xsl:value-of select="count(str:tokenize(ROOT/Var1,'|'))" />
Number of Values in Var2: <xsl:value-of select="count(str:tokenize(ROOT/Var2,'|'))" />
Common Values: <xsl:value-of select="count(set:intersection(str:tokenize(ROOT/Var1,'|'),str:tokenize(ROOT/Var2,'|'))/token)" />
<xsl:variable name="set1" select="str:tokenize(ROOT/Var1,'|')"/>
<xsl:variable name="set2" select="str:tokenize(ROOT/Var2,'|')"/>
<xsl:variable name="intersection" select="$set1[.=$set2]"/>
<xsl:value-of select="count($intersection)"/>
<xsl:for-each select="$intersection">
<xsl:value-of select="node()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

XML output with element value as tag name and next subsequent element value as value for the created tag

I need to form an output xml in which I need to have the field value as a tag and then the subsequent next field value as value for the created tag.
<PrimaryKey>
<PK1FeildName>CONNO</PK1FeildName>
<PK1Value>001</PK1Value>
<PK2FeildName>INNO</PK2FeildName>
<PK2Value>123</PK2Value>
<PK3FeildName>CONNO</PK3FeildName>
<PK3Value>011</PK3Value>
</PrimaryKey>
Expected output:
<PrimaryKey>
<CONNO>001</CONNO>
<INNO>123</INNO>
<CONNO>011</CONNO>
</PrimaryKey>
If we consider that the elements will always appear in pairs where the value of the first element is the tag name and the second element is the value, then this works :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="PrimaryKey">
<xsl:element name="PrimaryKey">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:if test="count(preceding-sibling::*) mod 2 = 0">
<xsl:element name="{.}">
<xsl:value-of select="following-sibling::*[1]"/>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
You can try it here : https://xsltfiddle.liberty-development.net/bwdws3
Edit to answer comment
Example XML :
<Document>
<PrimaryKey>
<PK1FeildName>CONNO</PK1FeildName>
<PK1Value>001</PK1Value>
<PK2FeildName>INNO</PK2FeildName>
<PK2Value>123</PK2Value>
<PK3FeildName>CONNO</PK3FeildName>
<PK3Value>011</PK3Value>
</PrimaryKey>
<PrimaryKey>
<PK1FeildName>CONNO2</PK1FeildName>
<PK1Value>0012</PK1Value>
<PK2FeildName>INNO2</PK2FeildName>
<PK2Value>1232</PK2Value>
<PK3FeildName>CONNO2</PK3FeildName>
<PK3Value>0112</PK3Value>
</PrimaryKey>
</Document>
Modified XSLT :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="PrimaryKey">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="PrimaryKey/*">
<xsl:if test="count(preceding-sibling::*) mod 2 = 0">
<xsl:element name="{.}">
<xsl:value-of select="following-sibling::*[1]"/>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bwdws3/1
For completeness, here's a solution that uses ESQL instead of XSLT:
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
-- Get a reference to the first instance of 'PK1FeildName'
DECLARE refPK REFERENCE TO InputRoot.XMLNSC.PrimaryKey.PK1FeildName[1];
WHILE LASTMOVE(refPK) DO
-- remember the field name
DECLARE keyName CHARACTER FIELDVALUE(refPK);
MOVE refPK NEXTSIBLING;
-- create the next field in the output
CREATE LASTCHILD OF OutputRoot.XMLNSC.Document.PrimaryKey TYPE NameValue NAME keyName VALUE FIELDVALUE(refPK);
MOVE refPK NEXTSIBLING;
END WHILE;
RETURN TRUE;
END;
Whether you use XSL or ESQL, I would recommend that you validate the incoming XML against an XSD because the mapping code depends on seeing specific tags in a specific order. You could add code to check the tag names, but XSD validation is a much easier solution.

I want to find the count of current element within its parent element using XSLT

<a>
<z/>
<b/>
<b/>
<b/>
<c/>
</a>
I want to find the count of 'b' within 'a' when my parsing current node is 'c' using XSLT.
Is it possible to do this using XSLT?
I am not aware of what the element name 'b' would be, i.e. for its preceding sibling.
If you are positioned on c tag, or whatever the element is actually called, then to get the count of the preceding siblings, you would do this...
<xsl:value-of select="count(preceding-sibling::*)" />
EDIT: In answer to your comment, if you don't want to count all siblings, but only the count of the immediately preceding one, and the ones with the same name before that, you could try this...
<xsl:value-of select="count(preceding-sibling::*[name() = name(current()/preceding-sibling::*[1])])" />
This would not work though in the case you had multiple c nodes under one parent...
<a>
<z/>
<b/>
<b/>
<b/>
<c/>
<z/>
<b/>
<c/>
</a>
In this case, you could define a key like this, to group elements by the unique id of the first following element with a different name:
<xsl:key name="keyc" match="*" use="generate-id(following-sibling::*[name() != name(current())][1])" />
Then you can get the count like so:
<xsl:value-of select="count(key('keyc', generate-id()))" />
Here are the three options in action....
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="keyc" match="*" use="generate-id(following-sibling::*[name() != name(current())][1])" />
<xsl:template match="c">
<c>
<example1>
<xsl:value-of select="count(preceding-sibling::*)" />
</example1>
<example2>
<xsl:value-of select="count(preceding-sibling::*[name() = name(current()/preceding-sibling::*[1])])" />
</example2>
<example3>
<xsl:value-of select="count(key('keyc', generate-id()))" />
</example3>
</c>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Use xsl:number. It prints out the numer of the current element, formatted as required.
There are various options concerning how to perform the numeration,
e.g. multi-level or alphabetic one.
Actually it is quite a powerful tool.
I want to find the count of 'b' within 'a' when my parsing current node is 'c'
Let me rephrase that:
you want to count all occurrences of <b> which are on the same level as <c>.
This XSLT does the job by calling an <xsl:template> with a parameter:
the local-name of the element to be counted (in this case 'b'):
<?xml version="1.0"?>
<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="//c"> <!-- select the desired target element -->
<xsl:call-template name="count">
<xsl:with-param name="elemName" select="'b'" /> <!-- name of the element -->
</xsl:call-template>
</xsl:template>
<xsl:template name="count"> <!-- count all matching elements before and after -->
<xsl:param name="elemName" />
<xsl:value-of select="count(preceding-sibling::*[local-name() = $elemName]) + count(following-sibling::*[local-name() = $elemName])" />
</xsl:template>
</xsl:stylesheet>
In the case of your example the output simply is:
3

Trying to find the following two rows in XBRL instance document

I am trying to find an xslt solution to the following problem I have.
I want to find a set of 3 subsequent rows that share the node name and an attribute but have a different values. The first row in the input contains an identifier, the second and third row contain values from a source system. I want to find the sets where the second and third row have different values.
E.g.
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">78923</eba7:mi235>
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">1111</eba7:mi235>
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">2222</eba7:mi235>
There might also be sets of rows with only an identifier, a set of a row with an identifier and only one row with a value from the source system or a set of rows where the second and third row have the same value.
E.g.
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x24-x195-x10-x4">78748</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x24-x195-x10-x4">0</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">78804</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">12345</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">12345</eba7:mi310>
These I don't want to find in the output.
The output I want to create is
<eba7:mi235 id="78923" value1="1111" value2="2222" />
The structure of the input is such that the rows are always ordered like this. So I tried to access them using position, but that didn't work.
Could anybody point me in the right direction? Is using position the right way?
I have attached an file with the input data below
Thanks.
Paul.
<?xml version="1.0" encoding="utf-8"?>
<xbrl xml:lang="en" xmlns="http://www.xbrl.org/2003/instance" xmlns:eba7="http://www.eba.europa.eu/xbrl/crr/dict/met" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:link="http://www.xbrl.org/2003/linkbase">
<link:schemaRef xlink:type="simple" xlink:href="http://www.eba.europa.eu/eu/fr/xbrl/crr/fws/corep/its-2013-02/2014-07-31/mod/corep_con.xsd" />
<context id="I-2014-E">
<entity>
<identifier scheme="http://www.dnb.nl/id">578</identifier>
</entity>
<period>
<instant>2014-12-31</instant>
</period>
</context>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x24-x195-x10-x4">78748</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x24-x195-x10-x4">0</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">78804</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">12345</eba7:mi310>
<eba7:mi310 contextRef="I-2014-E-dim-x42-x9-x25-x195-x10-x4">12345</eba7:mi310>
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">78923</eba7:mi235>
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">1111</eba7:mi235>
<eba7:mi235 contextRef="I-2014-E-dim-x43-x9-x156-x51-x14">2222</eba7:mi235>
</xbrl>
I don't think the question is defined well enough; it can be interpreted in several ways.
If we assume that you want to:
Group all the given elements based on both the tag name and the #contextRef value being the same; with the mutual position of the elements being irrelevant for this purpose;
Count the distinct values in each group; if there are three or more, write an element with the common tag name to the output, and add a numbered attribute for each distinct value in this group;
then it would be probably best to do something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xbrli="http://www.xbrl.org/2003/instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="k1" match="*" use="concat(name(), '|', #contextRef)"/>
<xsl:key name="k2" match="*" use="concat(name(), '|', #contextRef, '|', .)"/>
<xsl:template match="/xbrli:xbrl">
<xsl:copy>
<xsl:for-each select="*[count(.|key('k1', concat(name(), '|', #contextRef))[1])=1]">
<xsl:variable name="distinct-values" select="key('k1', concat(name(), '|', #contextRef)) [count(.|key('k2', concat(name(), '|', #contextRef, '|', .))[1])=1]"/>
<xsl:if test="count($distinct-values) >= 3">
<xsl:copy>
<xsl:for-each select="$distinct-values">
<xsl:attribute name="value{position()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
</xsl:copy>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Applied to the following well-formed test input:
<xbrl xmlns="http://www.xbrl.org/2003/instance" xmlns:eba7="http://www.eba.europa.eu/xbrl/crr/dict/met">
<eba7:a contextRef="x">11</eba7:a>
<eba7:a contextRef="x">12</eba7:a>
<eba7:a contextRef="y">21</eba7:a>
<eba7:a contextRef="y">22</eba7:a>
<eba7:a contextRef="y">23</eba7:a>
<eba7:b contextRef="x">31</eba7:b>
<eba7:b contextRef="x">32</eba7:b>
<eba7:b contextRef="x">33</eba7:b>
<eba7:b contextRef="x">33</eba7:b>
<eba7:c contextRef="x">41</eba7:c>
<eba7:c contextRef="x">41</eba7:c>
<eba7:c contextRef="x">42</eba7:c>
<eba7:c contextRef="x">42</eba7:c>
</xbrl>
the result will be:
<?xml version="1.0" encoding="utf-8"?>
<xbrl xmlns="http://www.xbrl.org/2003/instance" xmlns:eba7="http://www.eba.europa.eu/xbrl/crr/dict/met">
<eba7:a value1="21" value2="22" value3="23"/>
<eba7:b value1="31" value2="32" value3="33"/>
</xbrl>
Note:
You must be familiar with the Muenchian grouping method in order to understand this;
Numbered attributes are not good XML practice. I would suggest you (or the powers that be) reconsider this requirement.
Would this stylesheet solve your problem:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xbrli="http://www.xbrl.org/2003/instance" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="elements" match="*" use="#contextRef"/>
<xsl:template match="/xbrli:xbrl">
<xsl:copy>
<xsl:apply-templates select="*[#contextRef
and count(key('elements', #contextRef)) = 3
and key('elements', #contextRef)[2] != key('elements', #contextRef)[3]
and count(. | key('elements', #contextRef)[1]) = 1]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="id">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:attribute name="value1">
<xsl:value-of select="key('elements', #contextRef)[2]"/>
</xsl:attribute>
<xsl:attribute name="value2">
<xsl:value-of select="key('elements', #contextRef)[3]"/>
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Here, a key is declared to match elements with #contextRef being the identifier. The first template applies templates to the first elements with unique #contextRef(and also those which match other conditions like total elements with that #contextRef must be 3, and the second and thrid elements must not have the same value).
The next template matches these elements(from the first template), and creates the further output.

Using XSLT 2.0 to parse the values of multiple attributes into an array-like structure

I'd like to be able to select all the attributes of a certain type in a document (for example, //#arch) and then take that node set and parse the values out into second node set. When I say "parse", in specific I mean I want to turn a node set like this:
arch="value1;value2;value3"
arch="value1:value4"
into a node set like this:
arch="value1"
arch="value2"
arch="value3"
arch="value1"
arch="value4"
or something like that; I want to get the individual values out of the attributes and into their own node.
If I can get it to that state, I've got plenty of methods for sorting and duplicate removal, after which I'd be using the finished node set for a publishing task.
I'm not so much looking for an tidy answer here as an approach. I know that XSLT cannot do dynamic arrays, but that's not the same as not being able to do something like dynamic arrays or something that mimics the important part of the functionality.
One thought that has occurred to me is that I could count the nodes in the first node set, and the number of delimiters, calculate the number of entries that the second node set would need and create it (somehow), and use the substring functions to parse out the first node set into the second node set.
There's usually a way working around XSLT's issues; has anyone worked their way around this one before?
Thanks for any help,
Jeff.
I think what you're looking for is a sequence. A sequence can be either nodes or atomic values (see http://www.w3.org/TR/xslt20/#constructing-sequences).
Here's an example showing the construction of a sequence and then iterating over it. The sequence is the atomic values from #arch, but it could also be nodes.
XML Input
<doc>
<foo arch="value1;value2;value3"/>
<foo arch="value1:value4"/>
</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:variable name="archSequence" as="item()*">
<xsl:for-each select="//#arch">
<xsl:for-each select="tokenize(.,'[;:]')">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<sequence>
<xsl:for-each select="$archSequence">
<item><xsl:value-of select="."/></item>
</xsl:for-each>
</sequence>
</xsl:template>
</xsl:stylesheet>
XML Output
<sequence>
<item>value1</item>
<item>value2</item>
<item>value3</item>
<item>value1</item>
<item>value4</item>
</sequence>
Example of a sequence of elements (same output):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="archSequence" as="element()*">
<xsl:for-each select="//#arch">
<xsl:for-each select="tokenize(.,'[;:]')">
<item><xsl:value-of select="."/></item>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<sequence>
<xsl:for-each select="$archSequence">
<xsl:copy-of select="."/>
</xsl:for-each>
</sequence>
</xsl:template>
</xsl:stylesheet>
You can use the tokenize function in a for expression to get a sequence of the separate values, then create an attribute node for each one. However, since XSLT doesn't let you create a bare attribute node with no element parent, you'll have to use a trick like this:
<xsl:variable name="archElements">
<xsl:for-each select="for $attr in $initialNodeSet
return tokenize($attr, '[:;]')">
<dummy arch="{.}" />
</xsl:for-each>
</xsl:variable>
and then $archElements/dummy/#arch should be the set of separated arch attribute nodes that you require.
Complete example:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:variable name="inputData">
<a arch="value1;value2;value3" />
<a arch="value1:value4" />
</xsl:variable>
<!-- create an example node set containing the two arch attribute nodes -->
<xsl:variable name="initialNodeSet" select="$inputData/a/#arch" />
<!-- tokenize and generate one arch attribute node for each value -->
<xsl:variable name="archElements">
<xsl:for-each select="for $attr in $initialNodeSet
return tokenize($attr, '[:;]')">
<dummy arch="{.}" />
</xsl:for-each>
</xsl:variable>
<!-- output to verify -->
<r>
<xsl:for-each select="$archElements/dummy/#arch">
<c><xsl:copy-of select="."/></c>
</xsl:for-each>
</r>
</xsl:template>
</xsl:stylesheet>
When run over any input document (the content is ignored) this produces
<?xml version="1.0" encoding="UTF-8"?>
<r>
<c arch="value1"/>
<c arch="value2"/>
<c arch="value3"/>
<c arch="value1"/>
<c arch="value4"/>
</r>