XSL I need to remove space - xslt-1.0

I need to remove the white space between "|"
Example:
|| 3.3 | A | 001 | 2017-03-03T16:57:51 | 01 *20001000000200001437 | Only free ||
I need this output:
||3.3|A|001|2017-03-03T16:57:51|01 *20001000000200001437|Only free||

This is rather awkward to do in XSLT 1.0.
Given the following input:
XML
<root>
<item>|| 3.3 | A | 001 | 2017-03-03T16:57:51 | 01 *20001000000200001437 | Only free ||</item>
</root>
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="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:variable name="remove-left-spaces">
<xsl:call-template name="remove-spaces">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="delimiter" select="' |'"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="remove-spaces">
<xsl:with-param name="text" select="$remove-left-spaces"/>
<xsl:with-param name="delimiter" select="'| '"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="remove-spaces">
<xsl:param name="text"/>
<xsl:param name="delimiter"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="remove-spaces">
<xsl:with-param name="text">
<xsl:value-of select="substring-before($text, $delimiter)"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="substring-after($text, $delimiter)"/>
</xsl:with-param>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
will return:
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>||3.3|A|001|2017-03-03T16:57:51|01 *20001000000200001437|Only free||</item>
</root>

Related

Validation AlphaNumeric XSLT

I was stuck with validation. i can validation when empty string, and validation with length requirement, and validation with just numeric, But when the input was have a special character and have contains alphanumeric. i was stuck. can anyone helping me correct which side i need fix with my code
MYCODE :
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="LOCAL_XSLT_Validate" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<OperationValueRegex>
<xsl:call-template name="values">
<xsl:with-param name="vals" select="//OperationValueRegex/Value"/>
</xsl:call-template>
</OperationValueRegex>
</xsl:template>
<xsl:template name="values">
<xsl:param name="vals"/>
<xsl:choose>
<!-- Validation Number -->
<xsl:when test="fn:tokenize($vals, ' ')[matches(., '\d+')] and string-length($vals) = 8">
<Result1>
<xsl:value-of select="$vals"/>
</Result1>
</xsl:when>
<xsl:when test="$vals = 'NaN' or string-length($vals) != 8">
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>input was not valid requirement maximum</notification>
</Result1>
</xsl:when>
<xsl:otherwise>
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>Wrong Format</notification>
</Result1>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
</localEntry>
Request and expected result
{
"OperationValueRegex" : {
"Value" : "1234asdv"
}
}
<OperationValueRegex xmlns="http://ws.apache.org/ns/synapse" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<Result1>1234asdv</Result1>
<notification>Wrong Format</notification>
</OperationValueRegex>
Thanks
I can found the way for validation Alphanumeric
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="LOCAL_XSLT_Validate" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<OperationValueRegex>
<xsl:call-template name="values">
<xsl:with-param name="vals" select="//OperationValueRegex/Value"/>
</xsl:call-template>
<xsl:call-template name="dates">
<xsl:with-param name="dats" select="//OperationValueRegex/Date"/>
</xsl:call-template>
</OperationValueRegex>
</xsl:template>
<xsl:template name="values">
<xsl:param name="vals"/>
<xsl:choose>
<!-- Validation Number -->
<xsl:when test="fn:matches($vals, '^\d+$') and string-length($vals) = 8">
<Result1>
<xsl:value-of select="$vals"/>
</Result1>
</xsl:when>
<xsl:when test="$vals = 'NaN' or string-length($vals) != 8">
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>input was not valid requirement maximum</notification>
</Result1>
</xsl:when>
<xsl:when test="fn:matches($vals, '^[a-zA-Z0-9_]*$') and string-length($vals) > 0">
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>Wrong Format</notification>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="dates">
<xsl:param name="dats"/>
<xsl:variable name="dateString">
<xsl:value-of select="substring($dats,1,4)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring($dats,5,2)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring($dats,7,2)"/>
</xsl:variable>
<RequiredFormat>
<xsl:value-of select="format-date(xs:date($dateString), '[Y]/[M]/[D]')"/>
</RequiredFormat>
<OtherFormat>
<xsl:value-of select="format-date(xs:date($dateString), '[MNn] [D], [Y]')"/>
</OtherFormat>
</xsl:template>
</xsl:stylesheet>
</localEntry>
But I still have trouble with when input was have special character like = "#+./!~`*%^$()-#". Need little more help about this

XSLT 1.0 multiple call of a template

I need to replace strings in an XML file. I'm trying to use XSLT to do it. I want to use call-template for each string I need to replace.
When I make multiple call to the template, only the last call works fine.
The XML file I need to change : I want to replace the strings
‘
and
—
by spaces
<?xml version="1.0" encoding="UTF-8"?>
<RAPPORT>
<reason>start test_145 : ‘ and test_ 151 : — _end_test</reason>
</RAPPORT>
The template I use :
<xsl:template name="globalReplace">
<xsl:param name="outputString"/>
<xsl:param name="target"/>
<xsl:param name="replacement"/>
<xsl:choose>
<xsl:when test="contains($outputString,$target)">
<xsl:value-of select="concat(substring-before($outputString,$target),$replacement)"/>
<xsl:call-template name="globalReplace">
<xsl:with-param name="outputString" select="substring-after($outputString,$target)"/>
<xsl:with-param name="target" select="$target"/>
<xsl:with-param name="replacement" select="$replacement"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$outputString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The multiple calls :
<xsl:template match="text()">
<xsl:call-template name="globalReplace">
<xsl:with-param name="outputString" select="."/>
<xsl:with-param name="target" select="'‘'"/>
<xsl:with-param name="replacement" select="' '"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="text()">
<xsl:call-template name="globalReplace">
<xsl:with-param name="outputString" select="."/>
<xsl:with-param name="target" select="'—'"/>
<xsl:with-param name="replacement" select="' '"/>
</xsl:call-template>
</xsl:template>
Expected result :
<?xml version="1.0" encoding="UTF-8"?>
<RAPPORT>
<reason>debut test_test_145 et test 151 _fin test</reason>
</RAPPORT>
What I get in fact :
<?xml version="1.0" encoding="UTF-8"?>
<RAPPORT>
<reason>debut test_test_145**PUI** et test 151 _fin test</reason>
</RAPPORT>
PUI means an unexpected character instead of the needed space
You have two templates that match text(). Only the last of these is applied - see: https://www.w3.org/TR/1999/REC-xslt-19991116#conflict
In the given example, you could simply use the translate() function to do all the work at once, since the "strings" you want to replace are actually characters:
XML
<?xml version="1.0" encoding="UTF-8"?>
<RAPPORT>
<reason>start test_145 : ‘ and test_ 151 : — _end_test</reason>
</RAPPORT>
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="text()">
<xsl:value-of select="translate(., '‘—', ' ')"/>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<RAPPORT>
<reason>start test_145 : and test_ 151 : _end_test</reason>
</RAPPORT>
Many thanks !
It works fine this way !
I improved it inserting my result into a variable :
<xsl:template match="text()">
<xsl:variable name="premierePasse">
<xsl:value-of select="translate(., '‘—’',' ')"/>
</xsl:variable>
<xsl:value-of select="translate($premierePasse, 'œ', 'œ')"/>
</xsl:template>

Otherwise XSLT1.0 - correct output

I´ve a problem at my xslt.
Here it is:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GRP">
<xsl:copy>
<!--copy the data from ADD - ST to the GRP so it can be used in the mapping to set the delivery address from end customer-->
<xsl:for-each select ="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<xsl:copy-of select="PARTY_NAME_1"/>
<xsl:copy-of select="STREET_1"/>
<xsl:copy-of select="CITY"/>
<xsl:copy-of select="POSTAL_CODE"/>
<xsl:copy-of select="COUNTRY_CODE"/>
</xsl:if>
<xsl:choose>
<xsl:when test="./QUALIFIER='CN'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER"/>
</CONTACT_NUMBER>
</xsl:when>
<xsl:otherwise>
<xsl:if test="./QUALIFIER='ST'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER"/>
</CONTACT_NUMBER>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<!--copy all other nodes-->
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Can you tell me, whats my mistake at my xml?
At my code i get Contact_Number 2 times.
I just like one of them... If Contact at CN - use this, otherwise use from ST.
-> If contact at CN and ST use CN.
Edit: xml:
<SEEDELFOR>
<GRP>
<ADD>
<QUALIFIER>CN</QUALIFIER>
<IDENTIFIER></IDENTIFIER>
<AGENCY_CODE></AGENCY_CODE>
<PARTY_NAME_1></PARTY_NAME_1>
<STREET_1></STREET_1>
<CITY></CITY>
<POSTAL_CODE></POSTAL_CODE>
<COUNTRY_CODE></COUNTRY_CODE>
<CONTACT>
<QUALIFIER></QUALIFIER>
<NUMBER>1111111</NUMBER>
</CONTACT>
</ADD>
<ADD>
<QUALIFIER>ST</QUALIFIER>
<IDENTIFIER></IDENTIFIER>
<AGENCY_CODE></AGENCY_CODE>
<PARTY_NAME_1></PARTY_NAME_1>
<STREET_1></STREET_1>
<CITY></CITY>
<POSTAL_CODE></POSTAL_CODE>
<CONTACT>
<QUALIFIER></QUALIFIER>
<NUMBER>2222222</NUMBER>
</CONTACT>
</ADD>
</GRP>
</SEEDELFOR>
How can i correct my xslt?
I hope you can help me.
Best regards
Julian
One of the way you can achieve this is, rewriting the template GRP as following:
<xsl:template match="GRP">
<xsl:copy>
<!--copy the data from ADD - ST to the GRP so it can be used in the mapping
to set the delivery address from end customer -->
<xsl:variable name="contact_ST">
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER" />
</CONTACT_NUMBER>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="contact_CN">
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='CN'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER" />
</CONTACT_NUMBER>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<xsl:copy-of select="PARTY_NAME_1" />
<xsl:copy-of select="STREET_1" />
<xsl:copy-of select="CITY" />
<xsl:copy-of select="POSTAL_CODE" />
<xsl:copy-of select="COUNTRY_CODE" />
</xsl:if>
</xsl:for-each>
<xsl:choose>
<xsl:when test="$contact_CN != ''">
<xsl:copy-of select="$contact_CN" />
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$contact_ST" />
</xsl:otherwise>
</xsl:choose>
<!--copy all other nodes -->
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
Consider the following simplified example:
<xsl:template match="GRP">
<xsl:copy>
<!-- other code, if necessary-->
<xsl:variable name="cn" select="ADD[QUALIFIER='CN']" />
<xsl:variable name="st" select="ADD[QUALIFIER='ST']" />
<CONTACT_NUMBER>
<xsl:choose>
<xsl:when test="$cn">
<xsl:value-of select="$cn/CONTACT/NUMBER"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$st/CONTACT/NUMBER"/>
</xsl:otherwise>
</xsl:choose>
</CONTACT_NUMBER>
<!-- more code, if necessary-->
</xsl:copy>
</xsl:template>

XSL Replace an element by splitting it's values

I have the following XML which contains the order details in single element.
<?xml version="1.0" encoding="UTF-8"?>
<MESSAGE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MESSAGE_ID>361155</MESSAGE_ID>
<NAME>Header123</NAME>
<HEADERS>
<HEADER>
<ACTION_COUNT>1</ACTION_COUNT>
<ACTION_DESC>
<DAILY_LOAD>
<LOAD_NO>1</LOAD_NO>
<CUSTOMER_NO>09656951</CUSTOMER_NO>
<REFERENCE xsi:nil="1"/>
<SERIAL>450255470000403803</SERIAL>
<ORDERS>
<ORDER>
<ITEM>5000128762885</ITEM>
<DETAILS>4582;Robert and Co;8;5526;SWD</DETAILS>
<EMP_NO>13</EMP_NO>
<USE_BY_DATE>20110611</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
<ORDER>
<ITEM>5000128853613</ITEM>
<DETAILS>5000;Anne and Co;9;2020;ATM</DETAILS>
<EMP_NO>5</EMP_NO>
<USE_BY_DATE>20110613</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
</ORDERS>
</DAILY_LOAD>
</ACTION_DESC>
</HEADER>
</HEADERS>
<LIST_ID>23689</LIST_ID>
<TRAILER>TEST_NEEDED</TRAILER>
</MESSAGE>
I need that to be transformed into the following format.
(only the DAILY_LOAD>ORDERS section should be changed as below)
.....
<ORDERS>
<ORDER>
<ITEM>5000128762885</ITEM>
<ORDER_NO>4582</ORDER_NO>
<CUSTOMER>Robert and Co</CUSTOMER>
<NO_OF_ITEMS>8</NO_OF_ITEMS>
<TOTAL>5526</TOTAL>
<LOCATION>SWD</LOCATION>
<EMP_NO>13</EMP_NO>
<USE_BY_DATE>20110611</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
<ORDER>
<ITEM>5000128853613</ITEM>
<ORDER_NO>5000</ORDER_NO>
<CUSTOMER>Anne and Co</CUSTOMER>
<NO_OF_ITEMS>9</NO_OF_ITEMS>
<TOTAL>2020</TOTAL>
<LOCATION>ATM</LOCATION>
<EMP_NO>5</EMP_NO>
<USE_BY_DATE>20110613</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
</ORDERS>
.....
The transformed XML contains no but it's divided into CUSTOMER, NO_OF_ITEMS, TOTAL and LOCATION. Any suggestion or help will be highly appreciated.
Thank you in advance.
XSLT 1.0
Using tokenizeString template as suggested in Heber.it blog. I have modified the code for producing different tag names depending on recursion level (ORDER_NO, CUSTOMER, NO_OF_ITEMS, etc).
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<!-- replaces order nodes -->
<xsl:template match="ORDER">
<ORDER>
<xsl:call-template name="tokenizeString">
<xsl:with-param name="list" select="./DETAILS"/>
<xsl:with-param name="delimiter" select="';'"/>
<xsl:with-param name="level" select="1"/>
</xsl:call-template>
</ORDER>
</xsl:template>
<!-- copy everything that doesn't match another template -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- template to tokenize strings -->
<xsl:template name="tokenizeString">
<!--passed template parameter -->
<xsl:param name="list"/>
<xsl:param name="delimiter"/>
<xsl:param name="level"/>
<xsl:choose>
<xsl:when test="contains($list, $delimiter)">
<xsl:choose>
<xsl:when test="$level = 1">
<ITEM>
<xsl:value-of select="ITEM"/>
</ITEM>
<ORDER_NO>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</ORDER_NO>
</xsl:when>
<xsl:when test="$level = 2">
<CUSTOMER>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</CUSTOMER>
</xsl:when>
<xsl:when test="$level = 3">
<NO_OF_ITEMS>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</NO_OF_ITEMS>
</xsl:when>
<xsl:when test="$level = 4">
<TOTAL>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</TOTAL>
</xsl:when>
</xsl:choose>
<xsl:call-template name="tokenizeString">
<!-- store anything left in another variable -->
<xsl:with-param name="list" select="substring-after($list,$delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$list = ''">
<xsl:text/>
</xsl:when>
<xsl:otherwise>
<LOCATION>
<xsl:value-of select="$list"/>
</LOCATION>
<EMP_NO>
<xsl:value-of select="EMP_NO"/>
</EMP_NO>
<USE_BY_DATE>
<xsl:value-of select="USE_BY_DATE"/>
</USE_BY_DATE>
<DEPOT>
<xsl:value-of select="DEPOT"/>
</DEPOT>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0
Using tokenize function you can do this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<!-- this template replaces order nodes -->
<xsl:template match="ORDER">
<ORDER>
<xsl:variable name="fields" select="tokenize(DETAILS, ';')"/>
<ITEM>
<xsl:value-of select="ITEM"/>
</ITEM>
<ORDER_NO>
<xsl:value-of select="$fields[position()=1]"/>
</ORDER_NO>
<CUSTOMER>
<xsl:value-of select="$fields[position()=2]"/>
</CUSTOMER>
<NO_OF_ITEMS>
<xsl:value-of select="$fields[position()=3]"/>
</NO_OF_ITEMS>
<TOTAL>
<xsl:value-of select="$fields[position()=4]"/>
</TOTAL>
<LOCATION>
<xsl:value-of select="$fields[position()=5]"/>
</LOCATION>
<EMP_NO>
<xsl:value-of select="EMP_NO"/>
</EMP_NO>
<USE_BY_DATE>
<xsl:value-of select="USE_BY_DATE"/>
</USE_BY_DATE>
<DEPOT>
<xsl:value-of select="DEPOT"/>
</DEPOT>
</ORDER>
</xsl:template>
<!-- this template copies everything that doesn't match another template -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Modifying the XML element value upon condiion by XSLT

I have xml
<PhoneNumberDetails>
<PhoneNumber>
<Number>4162880001</Number>
<TimeStamp>2016-08-16T07:07:44-04:00</TimeStamp>
</PhoneNumber>
<PhoneNumber>
<Number>4162880002</Number>
<TimeStamp>2016-08-16T07:07:44-04:00</TimeStamp>
</PhoneNumber>
</PhoneNumberDetails>
This is input to a XSL. In this XSL i retrieve a phone number from context variable stored in one of the previous XSLT and if it matches to any phone number in above xml, I need to update the TimeStamp to new current Timestamp. I need help in this part.
The XSLT Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="dp date" exclude-result-prefixes="dp">
<xsl:variable name="currentTimeStamp" select="date:date-time()"/>
<xsl:output method="xml"/>
<xsl:template match="PhoneNumberDetails">
<xsl:variable name="savedPhoneNum" select="dp:variable('var://context/name/phonenum')"/>
<xsl:choose>
<xsl:when test="/*[local-name()='PhoneNumberDetails']/*[local-name()='PhoneNumber']/*[local-name()='Number']=$savedPhoneNum">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="phonenumber"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="phonenumber" match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PhoneNumberDetails">
<PhoneNumberDetails>
<xsl:apply-templates select="#* | *"/>
<PhoneNumber>
<Number>
<xsl:value-of select="dp:variable('var://context/name/phonenum')"/>
</Number>
<TimeStamp>
<xsl:value-of select="$currentTimeStamp"/>
</TimeStamp>
</PhoneNumber>
</PhoneNumberDetails>
</xsl:template>
</xsl:stylesheet>
If the phone number does not matches any number in XML i need to add a new element to the above xml and this part works. For e.g.
<PhoneNumber>
<Number>New number</Number>
<TimeStamp>Current TimeStamp</TimeStamp>
</PhoneNumber>
Why can't you do simply:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="dp date">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="savedPhoneNum" select="dp:variable('var://context/name/phonenum')"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TimeStamp[../Number=$savedPhoneNum]">
<xsl:copy>
<xsl:value-of select="date:date-time()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PhoneNumberDetails[not(PhoneNumber/Number=$savedPhoneNum)]">
<xsl:copy>
<xsl:apply-templates/>
<PhoneNumber>
<Number>New number</Number>
<TimeStamp>Current TimeStamp</TimeStamp>
</PhoneNumber>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I suggest you start with something like this. Don't use an absolute path to select the phone number, use it from that context node where the template matches.
<xsl:template match="PhoneNumber">
<xsl:copy>
<xsl:copy-of select="Number"/>
<xsl:variable name="savedPhoneNum" select="dp:variable('var://context/name/phonenum')"/>
<TimeStamp>
<xsl:choose>
<xsl:when test="Number=$savedPhoneNum">
<xsl:value-of select="$currentTimeStamp"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="TimeStamp"/>
</xsl:otherwise>
</xsl:choose>
</TimeStamp>
</xsl:copy>
</xsl:template>
Note that I assume that you don't have a (non-shown) namespace on the elements of your input xml. If yes, keep your *[local-name()=""] construct, but then the namespace would have to be added to the match="PhoneNumber" and to the TimeStamp output as well.