Reputation: 1
When i use XSLT 2.0 key and tokenize function, it's return items order getting changed based on key value. in our output we required retain the same order of tokenize sequence.
Input File
<?xml version="1.0" encoding="UTF-8"?> <a> <bd id="a">a</bd> <bd id="b">b</bd> <bd id="e">e</bd> <bd id="d">d</bd> </a>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="idcollect" match="*[@id]" use="@id" />
<xsl:variable name="name" select="'d,b,e,a'"/>
<xsl:template match="/">
<xsl:for-each select="key('idcollect',tokenize($name,','))" >
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
current Output
<?xml version="1.0" encoding="UTF-8"?><bd id="a">a</bd><bd id="b">b</bd><bd id="e">e</bd><bd id="d">d</bd>
Expected output
<?xml version="1.0" encoding="UTF-8"?><bd id="d">d</bd><bd id="b">b</bd><bd id="e">e</bd><bd id="a">a</bd>
Upvotes: 0
Views: 41
Reputation: 117140
Try:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="idcollect" match="*[@id]" use="@id" />
<xsl:variable name="name" select="'d,b,e,a'"/>
<xsl:template match="/">
<xsl:variable name="ids" select="tokenize($name,',')"/>
<xsl:for-each select="key('idcollect', $ids)" >
<xsl:sort select="index-of($ids, .)"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Or, if you prefer:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="idcollect" match="*[@id]" use="@id" />
<xsl:variable name="name" select="'d,b,e,a'"/>
<xsl:template match="/">
<xsl:variable name="xml" select="/"/>
<xsl:for-each select="tokenize($name, ',')" >
<xsl:copy-of select="key('idcollect', ., $xml)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Reputation: 167716
I think you want e.g.
<xsl:variable name="main-doc" select="/"/>
<xsl:for-each select="for $token in tokenize($name,',') return key('idcollect', $token, $main-doc)">
<xsl:copy-of select="."/>
</xsl:for-each>
or in XSLT 3
<xsl:variable name="main-doc" select="/"/>
<xsl:for-each select="tokenize($name,',') ! key('idcollect', ., $main-doc)">
<xsl:copy-of select="."/>
</xsl:for-each>
Of course in both cases the for-each/copy-of nesting is not needed and e.g.
<xsl:copy-of select="let $main-doc := / return tokenize($name,',') ! key('idcollect', ., $main-doc)"/>
or
<xsl:variable name="main-doc" select="/"/>
<xsl:copy-of select="for $token in tokenize($name,',') return key('idcollect', $token, $main-doc)"/>
would suffice.
Upvotes: 1