I am new to xslt programming and xlm. I have created the code below this works fine, except that instead variable names for each column, it just shows "colno" How do I get the column names into the output?
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
exclude-result-prefixes="fmp"
>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:variable name="kMetaData" select="fmp:METADATA/fmp:FIELD"/>
<xsl:variable name="colno"
select="count($kMetaData[following-sibling::fmp:FIELD/#NAME]) + 1" />
<xsl:template match="/fmp:FMPXMLRESULT">
<PERSON>
<xsl:apply-templates select="fmp:RESULTSET/fmp:ROW" />
</PERSON>
</xsl:template>
<xsl:template match="fmp:ROW">
<ELEMENTS>
<xsl:apply-templates select="fmp:COL" />
</ELEMENTS>
</xsl:template>
<xsl:template match="fmp:COL">
<xsl:element name="colno">
<xsl:value-of select="fmp:DATA" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
It is hard to make some suggestion without input xml. But at first sight this <xsl:element name="colno"> says "output an element <colno>". I think you should use something like <xsl:element name="{xpath/to/columnName}">
edit:
According to your input xml your template for "COL" element should look like
<xsl:template match="COL">
<xsl:variable name="colPosition" select="position()" />
<!-- Prevent spaces in NAME attribute of FIELD element -->
<xsl:variable name="colName" select="translate($kMetaData[$colPosition]/#NAME, ' ', '_')" />
<xsl:element name="{$colName}">
<xsl:value-of select="DATA"/>
</xsl:element>
</xsl:template>
Then the output looks like
<?xml version="1.0" encoding="utf-8"?>
<PERSON>
<ELEMENTS>
<FIRSTNAME>Richard</FIRSTNAME>
<LASTNAME>Katz</LASTNAME>
<MIDDLENAME>David</MIDDLENAME>
<REQUESTDT>1/1/2001</REQUESTDT>
<salutation>Mr</salutation>
<Bargaining_Unit>CSEA (02,03,04)</Bargaining_Unit>
<Field_134>b</Field_134>
</ELEMENTS>
</PERSON>
Related
I'm working on a Java based xsl-transformation (XSLT 2.0, could also be XSLT 3.0 if there is a free processor for java) with different input xml files. one input file could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<MyElement>
<CHILD>A</CHILD>
<CHILDBEZ>ABEZ</CHILDBEZ>
<NotInteresting></NotInteresting>
</MyElement>
<MyElement>
<CHILD>B</CHILD>
<CHILDBEZ>BBEZ</CHILDBEZ>
<NotInteresting2></NotInteresting2>
</MyElement>
</TEST>
I want to copy all elements but "NotInteresting" and rename the two nodes CHILD and CHILDBEZ based on two parameters that I get from a mapping file:
the xpath expression that tells me where the text of interest is placed (in this case: TEST/MyFirstElement/CHILD and TEST/MyFirstElement/CHILDBEZ)
and the names of the elements what they should have in the output file (in this case: childName and childBez)
the mapping file:
<?xml version="1.0" encoding="UTF-8"?>
<element root="TEST">
<childName>TEST/MyElement/CHILD</childName>
<childBez>TEST/MyElement/CHILDBEZ</childBez>
</element>
desired output:
<TEST>
<MyElement>
<childName>A</childName>
<childBez>ABEZ</childBez>
</MyElement>
<MyElement>
<childName>B</childName>
<childBez>BBEZ</childBez>
</MyElement>
</TEST>
what I have so far:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="2.0 "
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.apoverlag.at"
xmlns:apo="http://www.apoverlag.at">
<xsl:variable name="vars" select="document('mapping.xml')"/>
<xsl:param name="src" />
<xsl:variable name="path" xpath-default-namespace="" select="$src/path"/> <!-- = TEST/*-->
<xsl:template match="/">
<xsl:for-each select="$path">
<xsl:call-template name="buildNode">
<xsl:with-param name="currentNode" select="current()"></xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="buildNode">
<xsl:param name="currentNode" />
<xsl:element name="test">
<xsl:for-each select="$vars/element/#root">
<xsl:for-each select="$vars/element/*">
<xsl:element name="{name(.)}"> <xsl:value-of select="concat($currentNode,'/',current())" />
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:transform>
My problem is that:
<xsl:value-of select="concat($currentNode,'/',current())" />
gives me "/TEST/MyFirstElement/CHILD" when I try it hardcoded with:
<xsl:value-of select="$currentNode/CHILD" />
I receive my desired output. Can anyone give me a hint how to solve this problem?
I would suggest a radically different approach. To simplify, I have used a mapping document with full paths (starting with the / root node):
mapping xml
<element root="TEST">
<childName>/TEST/MyElement/CHILD</childName>
<childBez>/TEST/MyElement/CHILDBEZ</childBez>
</element>
XSLT 2.0
<xsl:stylesheet version="2.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:param name="mapping" select="document('mapping.xml')"/>
<xsl:key name="map" match="*" use="." />
<xsl:template match="/">
<xsl:variable name="first-pass">
<xsl:apply-templates mode="first-pass"/>
</xsl:variable>
<xsl:apply-templates select="$first-pass/*"/>
</xsl:template>
<xsl:template match="*" mode="first-pass">
<xsl:param name="parent-path"/>
<xsl:variable name="path" select="concat($parent-path, '/', name())" />
<xsl:variable name="replacement" select="key('map', $path, $mapping)" />
<xsl:element name="{if ($replacement) then name($replacement) else name()}">
<xsl:attribute name="original" select="not($replacement)"/>
<xsl:apply-templates mode="first-pass">
<xsl:with-param name="parent-path" select="$path"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[#original='true' and not(descendant::*/#original='false')]"/>
</xsl:stylesheet>
Result, when applied to the provided input:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<MyElement>
<childName>A</childName>
<childBez>ABEZ</childBez>
</MyElement>
<MyElement>
<childName>B</childName>
<childBez>BBEZ</childBez>
</MyElement>
</TEST>
I am facing an xslt/xpath problem and hope someone could help, in a few words here is what I try to achieve.
I have to transform an XML document where some nodes may be missing, these missing nodes are mandatory in the final result. I have the set of mandatory node names available in an xsl:param.
The base document is:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="TRANSFORM.xslt"?>
<BEGIN>
<CLIENT>
<NUMBER>0021732561</NUMBER>
<NAME1>John</NAME1>
<NAME2>Connor</NAME2>
</CLIENT>
<PRODUCTS>
<PRODUCT_ID>12</PRODUCT_ID>
<DESCRIPTION>blah blah</DESCRIPTION>
</PRODUCTS>
<PRODUCTS>
<PRODUCT_ID>13</PRODUCT_ID>
<DESCRIPTION>description ...</DESCRIPTION>
</PRODUCTS>
<OPTIONS>
<OPTION_ID>1</OPTION_ID>
<DESCRIPTION>blah blah blah ...</DESCRIPTION>
</OPTIONS>
<PROMOTIONS>
<PROMOTION_ID>1</PROMOTION_ID>
<DESCRIPTION>blah blah blah ...</DESCRIPTION>
</PROMOTIONS>
</BEGIN>
Here is the stylesheet so far:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:param name="mandatoryNodes" as="xs:string*" select=" 'PRODUCTS', 'OPTIONS', 'PROMOTIONS' "/>
<xsl:template match="/">
<xsl:apply-templates select="child::node()"/>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="BEGIN">
<xsl:element name="BEGIN">
<xsl:for-each select="$mandatoryNodes">
<!-- If there is no node with this name -->
<xsl:if test="count(*[name() = 'current()']) = 0">
<xsl:element name="{current()}" />
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="child::node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I tried the transformation in XML Spy, the xsl:iftest failed saying that 'current item is PRODUCTS of type xs:string.
I've tried the same xsl:if outside of a for-each and it seems to work ... what am I missing ?
Inside of <xsl:for-each select="$mandatoryNodes"> the context item is a string but you want to access the primary input document and its nodes so you need to store that document or the template's context node in a variable and use that e.g.
<xsl:template match="BEGIN">
<xsl:variable name="this" select="."/>
<xsl:element name="BEGIN">
<xsl:for-each select="$mandatoryNodes">
<!-- If there is no child node of `BEGIN` with this name -->
<xsl:if test="count($this/*[name() = current()]) = 0">
<xsl:element name="{current()}" />
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="child::node()"/>
</xsl:element>
</xsl:template>
I have several records from the DB for a corresponding record in a file.
Example
Record no. XML
<XML_FILE_HEADER file_name="sample.txt" />
<XML_RECORD record_number="1" name="John Doe" Age="21"/>
<XML_RECORD record_number="2" name""Jessica Sanchez" Age="23"/>
<XML_FILE_FOOTER total_records="2"/>
Now for each record I have an xslt template that would create the output file in xml.
For record no 1:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml"/>
<xsl:template match="XML_FILE_HEADER">
<xsl:element name="File">
<xsl:attribute name="FileName"><xsl:value-of select="#file_name"/></xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
For records 2 and 3:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="XML_RECORD">
<xsl:element name="Record">
<xsl:attribute name="Name"><xsl:value-of select="#name"/></xsl:attribute>
<xsl:element name="Details">
<xsl:attribute name="Age"><xsl:value-of select="#Age"/></xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
For record 4:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="XML_FILE_FOOTER">
<xsl:element name="Totals">
<xsl:attribute name="Total Records"><xsl:value-of select="#total_records"/></xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The problem with is is I would have an output of this after appending each record using the templates above:
<?xml version="1.0" encoding="UTF-8"?>
<File FileName="sample.txt"></File>
<Record Name="John Doe" Age="21"></Record>
<Record Name="Jessica Sanchez" Age="22"></Record>
<Totals Total Records="2"></Totals>
How would I be able to insert the Record and Totals elements under File? so that it would have an output like this:
<?xml version="1.0" encoding="UTF-8"?>
<File FileName="sample.txt">
<Record Name="John Doe" Age="21"></Record>
<Record Name="Jessica Sanchez" Age="22"></Record>
<Totals Total Records="2"></Totals>
</File>
Any help would be very much appreciated. Thanks.
As short and easy as this:
<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="/*">
<xsl:apply-templates select="XML_FILE_HEADER"/>
</xsl:template>
<xsl:template match="XML_FILE_HEADER">
<File FileName="{#file_name}">
<xsl:apply-templates select="../*[not(self::XML_FILE_HEADER)]"/>
</File>
</xsl:template>
<xsl:template match="XML_RECORD">
<Record name="{#name}" Age="{#Age}"/>
</xsl:template>
<xsl:template match="XML_FILE_FOOTER">
<Totals TotalRecords="{#total_records}"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML (corrected to be well-formed) document:
<t>
<XML_FILE_HEADER file_name="sample.txt" />
<XML_RECORD record_number="1" name="John Doe" Age="21"/>
<XML_RECORD record_number="2" name="Jessica Sanchez" Age="23"/>
<XML_FILE_FOOTER total_records="2"/>
</t>
the wanted, correct result is produced:
<File FileName="sample.txt">
<Record name="John Doe" Age="21"/>
<Record name="Jessica Sanchez" Age="23"/>
<Totals TotalRecords="2"/>
</File>
Explanation:
Proper use of templates.
Proper use of xsl:apply-templates for ordering the results.
Proper use of AVT (Attribute Value Templates).
Avoided the use of xsl:element
No use of xsl:call-template.
Implemented in "push style" almost completely.
What you want is the <xsl:call-template name="templatename" /> element. This allows you to call a template from inside another template.
Something like
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml"/>
<xsl:template match="/XML_FILE/XML_FILE_HEADER">
<xsl:element name="File">
<xsl:attribute name="FileName">
<xsl:value-of select="#file_name"/>
</xsl:attribute>
<xsl:for-each select="/XML_FILE/XML_RECORD">
<xsl:call-template name="RecordTemplate" />
</xsl:for-each>
<xsl:call-template name="TotalTemplate" />
</xsl:element>
</xsl:template>
<xsl:template name="RecordTemplate">
<xsl:element name="Record">
<xsl:attribute name="Name"><xsl:value-of select="#name"/></xsl:attribute>
<xsl:attribute name="Age"><xsl:value-of select="#Age"/></xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="/XML_FILE/XML_FILE_FOOTER" name="TotalTemplate">
<xsl:element name="Totals">
<xsl:attribute name="Total Records"><xsl:value-of select="#total_records"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
of course your input you have to be XML valid (i.e. have a single root node) like so
<XML_FILE>
<XML_FILE_HEADER file_name="sample.txt" />
<XML_RECORD record_number="1" name="John Doe" Age="21"/>
<XML_RECORD record_number="2" name""Jessica Sanchez" Age="23"/>
<XML_FILE_FOOTER total_records="2"/>
</XML_FILE>
I have written XSLT file with the following code:
<xsl:attribute name="subCode">
<xsl:value-of select="Field[#key='XY']"/>
</xsl:attribute>
Let's say that my INPUT XML looks like this:
[...]
<Field key="XY"/>
[...]
In this case my XSLT would generate the following output:
<SomeElement subCode="">
[...]
</SomeElement>
My question is: How to ged rid of empty attribute subCode=""?
I know that it is possible by using some conditional instruction like <xsl:if>, however, this seems to be an ugly solution (because I have thousands of similar attributes generated in my XSLT).
It must be done in the same XSLT. I cannot add post-processing in additional XSLT file.
Besides that, the output XML has got its XSD Schema defined. And the schema says that this attribute is optional. Maybe there is some way to apply that XSD schema for the output XML?
Thanks in advance for any help!
Use:
<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="/*">
<someElement>
<xsl:apply-templates mode="attr"/>
</someElement>
</xsl:template>
<xsl:template match="Field[#key='XY' and not(.='')]" mode="attr">
<xsl:attribute name="subCode">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t>
<Field key="XY"/>
</t>
the wanted, correct result (no attribute at all is generated) is produced:
when the source XML document is this:
<t>
<Field key="XY">1</Field>
</t>
the same transformation again produces the correct, wanted result;
<someElement subCode="1"/>
You can define a template to match the attribute which will give you the correct output for a missing #key but if you also add the predicate [.!=''] it should then also ignore the attributes with no value.
<xsl:template match="#key[.!='']">
<xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
Or in your example if you only want the #key='XY' matches use:
<xsl:template match="#key[.='XY']">
<xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
Edit: Here is a more complete example that I used to test this.
Source XML
<Fields>
<Field key="XY">A</Field>
<Field key="XY">B</Field>
<Field key="">C</Field>
<Field>D</Field>
</Fields>
Accompanying XSL
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<output>
<xsl:apply-templates />
</output>
</xsl:template>
<xsl:template match="Field">
<xsl:element name="NewField">
<xsl:apply-templates select="#*"/>
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="#key[.='XY']">
<xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Result
<output>
<NewField subCode="XY">A</NewField>
<NewField subCode="XY">B</NewField>
<NewField>C</NewField>
<NewField>D</NewField>
</output>
You should apply the following templates to your attributes:
This template matches all key the attributes who's value is 'XY':
<xsl:template match="#key['XY']">
<xsl:attribute name="subCode">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
This template matches all the key attributes with a (text)value longer than 0:
<xsl:template match="#key[string-length(.)]">
<xsl:attribute name="other">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
And finally this template matches all the attributes (*) that are empty:
<xsl:template match="#*[not(string-length(.))]" />
So if you have an input like
<?xml version="1.0"?>
<Root>
<Field key='v'>One</Field>
<Field key='XY'>Two</Field>
<Field key='a'>Three</Field>
<Field key='v'>Four</Field>
<Field key='XY'>Five</Field>
<Field>Six</Field>
<Field>Seven</Field>
<Field key='b'>Eight</Field>
<Field key=''>Nine</Field>
<Field></Field>
<Field key='x'>Eleven</Field>
<Field key=''>Twelve</Field>
<Field lat='x'>Thirteen</Field>
</Root>
You can generate an output:
<?xml version='1.0' ?>
<Root>
<SomeField other="v">One</SomeField>
<SomeField subCode="XY">Two</SomeField>
<SomeField other="a">Three</SomeField>
<SomeField other="v">Four</SomeField>
<SomeField subCode="XY">Five</SomeField>
<SomeField>Six</SomeField>
<SomeField>Seven</SomeField>
<SomeField other="b">Eight</SomeField>
<SomeField>Nine</SomeField>
<SomeField/>
<SomeField other="x">Eleven</SomeField>
<SomeField>Twelve</SomeField>
<SomeField>xThirteen</SomeField>
</Root>
using the following xslt:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="Field">
<xsl:element name="SomeField">
<xsl:apply-templates select="#*"/>
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#key['XY']">
<xsl:attribute name="subCode">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="#key[string-length(.)]">
<xsl:attribute name="other">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="#key[not(string-length(.))]" />
</xsl:stylesheet>
I have a list of items:
<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>
and I want as output
z
c
x
a
I have no order information in the file and I just want to reverse the lines. The last line in the source file should be first line in the output. How can I solve this problem with XSLT without sorting by the content of the items, which would give the wrong result?
I will present two XSLT solutions:
I. XSLT 1.0 with recursion Note that this solution works for any node-set, not only in the case when the nodes are siblings:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:call-template name="reverse">
<xsl:with-param name="pList" select="*"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="reverse">
<xsl:param name="pList"/>
<xsl:if test="$pList">
<xsl:value-of
select="concat($pList[last()], '
')"/>
<xsl:call-template name="reverse">
<xsl:with-param name="pList"
select="$pList[not(position() = last())]"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<t>
<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>
</t>
produces the wanted result:
z
c
x
a
II. XSLT 2.0 solution :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:value-of select="reverse(*)/string(.)"
separator="
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the same XML document, the same correct result is produced.
XML CODE:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<device>
<element>a</element>
<element>x</element>
<element>c</element>
<element>z</element>
</device>
XSLT CODE:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//device">
<xsl:for-each select="element">
<xsl:sort select="position()" data-type="number" order="descending"/>
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
note: if you're using data-type="number", and any of the values aren't numbers, those non-numeric values will sort before the numeric values. That means if you're using order="ascending", the non-numeric values appear first; if you use order="descending", the non-numeric values appear last.
Notice that the non-numeric values were not sorted; they simply appear in the output document in the order in which they were encountered.
also, you may find usefull to read this:
http://docstore.mik.ua/orelly/xml/xslt/ch06_01.htm
Not sure what the full XML looks like, so I wrapped in a <doc> element to make it well formed:
<doc>
<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>
</doc>
Running that example XML against this stylesheet:
<?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" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:call-template name="reverse">
<xsl:with-param name="item" select="doc/item[position()=last()]" />
</xsl:call-template>
</xsl:template>
<xsl:template name="reverse">
<xsl:param name="item" />
<xsl:value-of select="$item" />
<!--Adds a line feed-->
<xsl:text>
</xsl:text>
<!--Move on to the next item, if we aren't at the first-->
<xsl:if test="$item/preceding-sibling::item">
<xsl:call-template name="reverse">
<xsl:with-param name="item" select="$item/preceding-sibling::item[1]" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Produces the requested output:
z
c
x
a
You may need to adjust the xpath to match your actual XML.
Consider this XML input:
<?xml version="1.0" encoding="utf-8" ?>
<items>
<item>a</item>
<item>x</item>
<item>c</item>
<item>z</item>
</items>
The XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/items[1]">
<xsl:variable name="items-list" select="." />
<xsl:variable name="items-count" select="count($items-list/*)" />
<xsl:for-each select="item">
<xsl:variable name="index" select="$items-count+1 - position()"/>
<xsl:value-of select="$items-list/item[$index]"/>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
And the result:
z
c
x
a