WSO2 ESB escaping xml entity to correct form - xml-entities

I am stuck on creating an output message from wso2 esb 5.0. The correct form of the message should be:
<request lang="11" user="user" pwd="pwd">
<query dateformat="%d-%m-%Y" maxrecords="100">
<tables>
<table tablename="Company"/>
</tables>
<condition>
<cond tablename="Company" fieldname="Upd" op=">" value="10.11.2016"/>
<cond tablename="Company" fieldname="UpdTime" op=">" value="01:00"/>
</condition>
The fun part is ">" in the "op" attribute. There has to be ">" and not ">". CDATA and this character also doesn`t work:
&
I tried with payload factory, xslt transformation and script mediator with different values but with no success. My bad attempts:
<payloadFactory description="Create Request" media-type="xml">
<format>
<request lang="11" user="user" pwd="pwd">
<query dateformat="%d-%m-%Y" maxrecords="100">
<tables>
<table tablename="Company"/>
</tables>
<condition>
<cond tablename="Company" fieldname="Upd" op=">" value="07.10.2016"/>
<cond tablename="Company" fieldname="UpdTime" op=">" value="01:00"/>
</condition>
</query>
</request>
</format>
<args/>
</payloadFactory>
With XSLT:
<xslt description="Create Request" key="get-companies"/>
<localEntry key="get-companies" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet exclude-result-prefixes="ws" version="1.0" xmlns:ws="http://ws.company.com/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="no"/>
<xsl:template match="/">
<xsl:element name="request">
<xsl:attribute name="lang">11</xsl:attribute>
<xsl:attribute name="user">user</xsl:attribute>
<xsl:attribute name="pwd">pwd</xsl:attribute>
<xsl:element name="query">
<xsl:attribute name="maxrecords">100</xsl:attribute>
<xsl:attribute name="dateformatin">%d-%m-%Y</xsl:attribute>
<tables xmlns="">
<table tablename="Company"/>
</tables>
<condition xmlns="">
<xsl:element name="cond">
<xsl:attribute name="tablename">Company</xsl:attribute>
<xsl:attribute name="fieldname">Upd</xsl:attribute>
<xsl:attribute name="op">></xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="07.01.2016"/>
</xsl:attribute>
</xsl:element>
<cond fieldname="UpdTime" op=">" tablename="Company" value="01:00"/>
</condition>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Script Mediator:
<script language="js"><![CDATA[mc.setPayloadXML(<request lang="11" user="user" pwd="pwd">
<query dateformat="%d-%m-%Y" maxrecords="100">
<tables>
<table tablename="Company"/>
</tables>
<condition>
<cond tablename="Company" fieldname="Upd" op="&gt;" value="07.01.2016"/>
<cond tablename="Company" fieldname="UpdTime" op="&gt;" value="01:00"/>
</condition>
</query>
</request>); ]]></script>
Please help me to find the correct form.

Related

Test for xsi:nil="true"

I wish to test for xsi:nil="true".
I'm using the replies from kjhughes & Michael Kay in these posts, respectively.
How to implement if-else statement in XSLT?
How do I check if XML value is nil in XSLT
XML:
<OSM>
<EstablishmentDetail>
<RatingValue>5</RatingValue>
<RatingDate>2008-05-15</RatingDate>
</EstablishmentDetail>
<EstablishmentDetail>
<RatingValue>AwaitingInspection</RatingValue>
<RatingDate xsi:nil="true"/>
</EstablishmentDetail>
</OSM>
A snip of the XSL:
<xsl:template>
"Value": "<xsl:value-of select="if (nilled(RatingDate)) then RatingValue else 'XX' "/>",
</xsl:template>
It's producing output but both are 'XX'. Is it just a syntax error?
The function https://www.w3.org/TR/xpath-functions/#func-nilled is meant to work with schema-aware XSLT and validated input i.e. if you use Saxon EE you can expect it to do its job:
In practice, the function returns true only for an element node that
has the attribute xsi:nil="true" and that is successfully validated
against a schema that defines the element to be nillable;
Need to add the namespace in the input document:
<OSM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EstablishmentDetail>
<RatingValue>5</RatingValue>
<RatingDate>2008-05-15</RatingDate>
</EstablishmentDetail>
<EstablishmentDetail>
<RatingValue>AwaitingInspection</RatingValue>
<RatingDate xsi:nil="true"/>
</EstablishmentDetail>
</OSM>
I'm not getting the right value out of the standard fn:nilled() function hence substituted a user function:
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:l="local:functions">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<RatingValues>
<xsl:for-each select="//EstablishmentDetail">
<EstablishmentDetail index="{position()}" >
<RatingValue>
<xsl:value-of select="('XX'[l:nilled(current()/RatingDate) ],
current()/RatingValue)[1]" />
</RatingValue>
<Nilled>
<xsl:value-of select="nilled(RatingDate)" />
</Nilled>
</EstablishmentDetail>
</xsl:for-each>
</RatingValues>
</xsl:template>
<xsl:function name="l:nilled" as="xs:boolean" >
<xsl:param name="e" as="element()" />
<xsl:sequence select="exists($e/#xsi:nil) and $e/#xsi:nil eq 'true'" />
</xsl:function>
</xsl:stylesheet>
which produces:
<?xml version="1.0" encoding="UTF-8"?>
<RatingValues xmlns:l="local:functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EstablishmentDetail index="1">
<RatingValue>5</RatingValue>
<Nilled>false</Nilled>
</EstablishmentDetail>
<EstablishmentDetail index="2">
<RatingValue>XX</RatingValue>
<Nilled>false</Nilled>
</EstablishmentDetail>
</RatingValues>
The Nilled elements in the output just to show that I'm getting false for both cases.

Dynamically replacing substring in an given data(XML to fixed length)

Actually I have started with my XSLT work recently, I am facing difficulty in solving one of the requirement.
I am trying to fetch an substring from DATA element in the mentioned input i,e is ECHO and OKAY these codes need to be replaced with the values present under CODE/ECHO and CODE/OKAY in the same input. I had tried storing the substring in a variable and as the variable value and tag value would be same, I have tried to fetch that in . But its not working.
Is it that we cant use variables in the XPATHS or there is some other representation which needs to be used? Could anyone please help me with this.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:variable name="String" select="substring(DATA, (string-length(substring(DATA,0,77)) + 1), 4)" />
<xsl:variable name="String1" >
<xsl:value-of select="Root/CODES/$String" />
</xsl:variable>
<xsl:value-of select="$break" />
<xsl:value-of select="$String1" />
</xsl:for-each>
</xsl:template>
Input:
<?xml version='1.0' encoding='utf-8'?>
<ROOT>
<INPUT>
<I_FILENAME>ERES</I_FILENAME>
</INPUT>
<CODES>
<ECHO>A1</ECHO>
<OKAY>A2</OKAY>
</CODES>
<TABLES>
<T_ER>
<item>
<DATA> HEADERERESRGCITIS220190301124112000000RGERSD46</DATA>
</item>
<item>
<DATA>000000 ABCD EF 0000000000 2018-11-060000000000EF 000000000000010000ECHO00400300000000000XXXXXX 000{ P 2018-11-05</DATA>
</item>
<item>
<DATA>000000 ABCD EF 0000000000 2018-11-060000000000EF 000000000000010000OKAY00400300000000000XXXXXX 000{ P 2018-11-05</DATA>
</item>
<item>
<DATA>TRAILERERESRGCITIS220190301124112000000001570000</DATA>
</item>
</T_ER>
</TABLES>
</ROOT>
EXPECTED OUT PUT:
HEADERERESRGCITIS220190301124112000000RGERSD46
000000 ABCD EF 0000000000 2018-11-060000000000EF 000000000000010000A100400300000000000XXXXXX 000{ P 2018-11-05
000000 ABCD EF 0000000000 2018-11-060000000000EF 000000000000010000A200400300000000000XXXXXX 000{ P 2018-11-05
<xsl:template match="INPUT|CODES">
</xsl:template>
<xsl:template match="TABLES">
<xsl:variable name="break" select="'
'" />
<xsl:for-each select="T_ER/item"><xsl:value-of select="$break"></xsl:value-of>
<xsl:value-of select="DATA"/>
</xsl:for-each>
</xsl:template>

XSLT- Pre Define NameSpace

Hi I have an XML that upon each delivery has a different unique named Namespace that I cannot pre determine with standard processes.
<ABC xmlns:this="urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>111</TaggedValue>
</this:ABDList>
<this:SubBegin>0</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>222</TaggedValue>
</this:ABDList>
<this:SubBegin>1</this:SubBegin>
</MatPackage>
<!-- Stuff -->
</Extention>
</Extentions>
</ABC>
The Next XML delivered could be
<ABC xmlns:this="urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>333</TaggedValue>
</this:ABDList>
<this:SubBegin>0</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>444</TaggedValue>
</this:ABDList>
<this:SubBegin>1</this:SubBegin>
</MatPackage>
<!-- Stuff -->
</Extention>
</Extentions>
</ABC>
My current XSL stylesheet works on the first XML predefining the Namespace
But I am looking to find a way to re-define it later on. on the process. I have added a variable to pull the relevant uuid from the Identification element but am not sure how to integrate this. Using the below stylesheet to process any other XML results in false results.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:this="urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:variable name="SelOpGroup" select="/ABC/Extensions/Identification"/>
<!-- Pass thru --->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ABC/Extensions/SrcPackage>
<xsl:copy>
<this:ABDList>
<xsl:copy-of select ="this:ABDList/*"/>
<TaggedA>888</TaggedA>
</this:ABDList>
<this:SubBegin><xsl:value-of select="somethingelse"/> </this:SubBegin>
</xsl:copy>
</xsl:template>
<xsl:template match="/ABC/Extensions/MatPackage>
<xsl:copy>
<this:ABDList>
<xsl:copy-of select ="this:ABDList/*"/>
<TaggedB>999</TaggedB>
</this:ABDList >
<this:SubBegin><xsl:value-of select="somethingelse"/> </this:SubBegin>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Expected Result
<ABC xmlns:this="urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>333</TaggedValue>
<TaggedA>888</TaggedA>
</this:ABDList>
<this:SubBegin>a value</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>444</TaggedValue>
<TaggedB>999</TaggedA>
</this:ABDList>
<this:SubBegin>a value</this:SubBegin>
</MatPackage>
<!-- Stuff -->
</Extention>
</Extentions>
</ABC>
Many thanks,
Adrian
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:variable name="SelOpGroup" select="/ABC/Extensions/Identification"/>
<!-- Pass thru -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Extension/SrcPackage">
<xsl:copy>
<xsl:element name="{'this:ABDList'}" namespace="{$SelOpGroup}">
<xsl:copy-of select="/*/namespace::*[name()='this']"/>
<xsl:copy-of select ="*[name() = 'this:ABDList']/*"/>
<TaggedA>888</TaggedA>
</xsl:element>
<xsl:element name="{'this:SubBegin'}" namespace="{$SelOpGroup}">
<xsl:copy-of select="/*/namespace::*[name()='this']"/>
<xsl:value-of select="'somethingelse'"/>
</xsl:element>
</xsl:copy>
</xsl:template>
<xsl:template match="Extension/MatPackage">
<xsl:copy>
<xsl:element name="{'this:ABDList'}" namespace="{$SelOpGroup}">
<xsl:copy-of select="/*/namespace::*[name()='this']"/>
<xsl:copy-of select ="*[name() = 'this:ABDList']/*"/>
<TaggedB>999</TaggedB>
</xsl:element>
<xsl:element name="{'this:SubBegin'}" namespace="{$SelOpGroup}">
<xsl:copy-of select="/*/namespace::*[name()='this']"/>
<xsl:value-of select="'somethingelse'"/>
</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied on the first provided XML document:
<ABC xmlns:this="urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>111</TaggedValue>
</this:ABDList>
<this:SubBegin>0</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>222</TaggedValue>
</this:ABDList>
<this:SubBegin>1</this:SubBegin>
</MatPackage>
<!-- Stuff -->
</Extension>
</Extensions>
</ABC>
Produces the wanted, correct result:
<ABC xmlns:this="urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1f15a9-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>111</TaggedValue>
<TaggedA>888</TaggedA>
</this:ABDList>
<this:SubBegin>somethingelse</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>222</TaggedValue>
<TaggedB>999</TaggedB>
</this:ABDList>
<this:SubBegin>somethingelse</this:SubBegin>
</MatPackage><!-- Stuff -->
</Extension>
</Extensions>
</ABC>
When the same transformation is applied on the second provided XML document:
<ABC xmlns:this="urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>333</TaggedValue>
</this:ABDList>
<this:SubBegin>0</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>444</TaggedValue>
</this:ABDList>
<this:SubBegin>1</this:SubBegin>
</MatPackage>
<!-- Stuff -->
</Extension>
</Extensions>
</ABC>
Again the wanted, correct result is produced:
<ABC xmlns:this="urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331" version="1.1">
<Extensions>
<Identification>urn:uuid:9b1FFae4-69de-11d2-b6bc-fcab70ff7331</Identification>
<Extension>
<SrcPackage>
<this:ABDList>
<TaggedValue>333</TaggedValue>
<TaggedA>888</TaggedA>
</this:ABDList>
<this:SubBegin>somethingelse</this:SubBegin>
</SrcPackage>
<MatPackage>
<this:ABDList>
<TaggedValue>444</TaggedValue>
<TaggedB>999</TaggedB>
</this:ABDList>
<this:SubBegin>somethingelse</this:SubBegin>
</MatPackage><!-- Stuff -->
</Extension>
</Extensions>
</ABC>
This is bizarre input (what were they smoking?). But since the namespace is only used on one element, ABDList, my approach would be to select the ABDList elements using *:ABDList in XSLT 2.0, or *[local-name()='ABDList'] in XSLT 1.0.
I have an XML that upon each delivery has a different unique named
Namespace
Someone ahead of you obviously does not understand the purpose of having a namespace.
Perhaps this could work for your unfortunate situation:
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="SrcPackage/*/TaggedValue">
<xsl:copy-of select="."/>
<TaggedA>888</TaggedA>
</xsl:template>
<xsl:template match="MatPackage/*/TaggedValue">
<xsl:copy-of select="."/>
<TaggedB>999</TaggedB>
</xsl:template>
</xsl:stylesheet>

Removing duplicate attribute in XSLT

I understand this is one such common question posted many times, but unfortunately I am unable to find an exact solution with any of the proposed approaches:
Here's how my XML looks like:
<root>
<parent>
<table>
<attr ......>
<type t="enumone">
<info>
<name .....>
</info>
</attr>
<attr>
<type t="int">
<range min="1" max="255"/>
</type>
<info>
<name .....>
</info>
</attr>
<attr>
<type t="string">
<info>
<name .....>
</info>
</attr>
<attr ......>
<type t="enumtwo">
<info>
<name .....>
</info>
</attr>
<attr>
<type t="float">
<range min="1.0" max="25.5"/>
</type>
<info>
<name .....>
</info>
</attr>
<attr>
<type t="int">
<info>
<name .....>
</info>
</attr>
<attr>
<type t="enumone">
<info>
<name .....>
</info>
</attr>
<attr>
<type t="enumthree">
<info>
<name .....>
</info>
</attr>
<attr>
<type t="enumone">
<info>
<name .....>
</info>
</attr>
</parent>
</root>
The intention is to retrieve one occurrence of attribute "#t" from "type" element by using XSLT:
Using for-each-group:
<xsl-template match="/root/parent">
<xsl:for-each select="table">
<xsl:for-each-group select="//type" group-by="#t">
<xsl:copy-of select="current-group( )[1]"/>
</xsl:for-each-group>
</xsl:for-each>
<xsl-template>
But I got no output! Something flawed I believe.
Using distinct-values():
<xsl:for-each select="distinct-values(type/#t)">
<xsl:sort/>
<xsl:value-of select="."/> <xsl:call-template name="newline"/>
</xsl:for-each>
Still no desired output.
The expected output is:
enumone
int
string
enumtwo
float
enumthree
Appreciate any help in this regard.
Well the input sample is not well-formed XML but if you really only want the distinct t attribute values of all type elements then doing
<xsl:template match="/">
<xsl:value-of select="distinct-values(//type/#t)" separator="
"/>
</xsl:template>
suffices with XSLT 2.0.
If you additionally want to sort the distinct values then doing
<xsl:template match="/">
<xsl:value-of separator="
">
<xsl:perform-sort select="distinct-values(//type/#t)">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:value-of>
</xsl:template>
To give a complete example, with the input being
<root>
<foo>
<type t="int"/>
</foo>
<bar>
<type t="enum"/>
</bar>
<foobar>
<foo>
<type t="enum">
<x/>
</type>
</foo>
</foobar>
<foo>
<type t="string"/>
</foo>
</root>
the stylesheet
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of separator="
">
<xsl:perform-sort select="distinct-values(//type/#t)">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:value-of>
</xsl:template>
</xsl:stylesheet>
outputs
enum
int
string
Just modify your code to this:
<xsl:template match="/">
<xsl:for-each-group select="//type" group-by="#t">
<xsl:copy-of select="current-group( )[1]"/>
</xsl:for-each-group>
</xsl:template>
The complete transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:for-each-group select="//type" group-by="#t">
<xsl:copy-of select="current-group( )[1]"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
When applied on a well-formed XML document:
<root>
<foo>
<type t="int"/>
</foo>
<bar>
<type t="enum"/>
</bar>
<foobar>
<foo>
<type t="enum">
<x/>
</type>
</foo>
</foobar>
<foo>
<type t="string"/>
</foo>
</root>
the correct result is produced:
<type t="int"/>
<type t="enum"/>
<type t="string"/>

XSLT - make xsl:analyze-string return string instead of sequence of strings?

Is it possible to make xsl:analyze-string return one string instead of a sequence of strings?
Background: I'd like to use xsl:analyze-string in a xsl:function that should encapsulate the pattern matching. Ideally, the function should return an xs:string to be used as sort criteria in an xsl:sort element.
At the moment, i have to apply string-join() on every result of the function call since xsl:analyze-string returns a sequence of strings, and xsl:sort doesn't accept such a sequence as sort criteria. See line 24 of the stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="www.my-personal-namespa.ce"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes" method="xml" />
<xsl:function name="my:sortierung" >
<xsl:param name="inputstring" as="xs:string"/>
<xsl:analyze-string select="$inputstring" regex="[0-9]+">
<xsl:matching-substring>
<xsl:value-of select="format-number(number(.), '00000')" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:function>
<xsl:template match="/input">
<result>
<xsl:apply-templates select="value" >
<xsl:sort select="string-join((my:sortierung(.)), ' ')" />
</xsl:apply-templates>
</result>
</xsl:template>
<xsl:template match="value">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
with this input:
<?xml version="1.0" encoding="UTF-8"?>
<input>
<value>A 1 b 120</value>
<value>A 1 b 1</value>
<value>A 1 b 2</value>
<value>A 1 b 1a</value>
</input>
In my example, is there a way to modify the xsl:function to return a xs:string instead of a sequence?
There are several ways I think, you could put the result of the analyze-string into a variable inside of the function and then use xs:sequence select="string-join($var, ' ')" in the function.
However the following with xsl:value-of should also do:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="www.my-personal-namespa.ce"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="my xs">
<xsl:output indent="yes" method="xml" />
<xsl:function name="my:sortierung" as="xs:string">
<xsl:param name="inputstring" as="xs:string"/>
<xsl:value-of separator=" ">
<xsl:analyze-string select="$inputstring" regex="[0-9]+">
<xsl:matching-substring>
<xsl:value-of select="format-number(number(.), '00000')" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:value-of>
</xsl:function>
<xsl:template match="/input">
<result>
<xsl:apply-templates select="value" >
<xsl:sort select="my:sortierung(.)" />
</xsl:apply-templates>
</result>
</xsl:template>
<xsl:template match="value">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

Resources