0

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>
HiDeoo
  • 10,353
  • 8
  • 47
  • 47

2 Answers2

0

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.

Stefan Hegny
  • 2,107
  • 4
  • 23
  • 26
0

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>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thanks Michael for you help!! Could you please let me know how can I extract the timestamp from the matched Number=@savedPhoneNu‌​m inside the template match – karthik rao Aug 17 '16 at 10:40
  • @karthikrao If you mean inside the template matching `TimeStamp[../Number=$savedPhoneNum]`, the exisitng value can be extracted by referring to the `.` context node - e.g. ``. – michael.hor257k Aug 17 '16 at 11:00