Hi,
i have the folwing xml, i want to compare the dates Modifyts and ActualDate using XPATH and XSLT and print the date which is newer.Can you please help me regarding this.

<ABC>
    <InputDocument>
        <OrderList LastOrderHeaderKey="2011013111595948350"
            LastRecordSet="Y" ReadFromHistory="" TotalOrderList="1">
            <Order DocumentType="0001" EnterpriseCode="XYZ"
                Modifyts="2011-02-14T13:53:04+00:00" OrderNo="Y100000042"/>
        </OrderList>
    </InputDocument>
    <EnvironmentDocument>
        <Order DocumentType="0001" EnterpriseCode="XYZ"
            MaximumRecords="5000" OrderNo="Y100000042">
            <OrderDates>
                <OrderDate ActualDate="2011-02-15T08:12:13.5551986Z" DateTypeId="ACK_DATETIME"/>
            </OrderDates>
        </Order>
    </EnvironmentDocument>
<ABC>

Thanks
Soumya

Dani AI

Generated

The two timestamps in the thread are ISO‑8601 style but use slightly different forms (an offset like +00:00 vs Z and fractional seconds). That difference is the key: reliable “which is newer” answers come from either using a true datetime type (XSLT 2.0 / XPath 2.0) or from carefully normalizing both strings before comparing in XSLT 1.0. correctly pointed to extension-based approaches and ’s manual parsing shows how to do it without extensions; the points below expand on those options and give practical cautions.

When XSLT 2.0 is available the simplest, most robust solution is to cast to dateTime and compare. Example (concept only):

<xsl:variable name="m" select="/ABC/InputDocument/OrderList/Order/@Modifyts"/>
<xsl:variable name="a" select="/ABC/EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate"/>

<xsl:choose>
  <xsl:when test="xs:dateTime($m) gt xs:dateTime($a)">
    <xsl:value-of select="$m"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="$a"/>
  </xsl:otherwise>
</xsl:choose>

Casting handles timezone offsets and fractional seconds correctly, so comparisons are accurate.

If restricted to XSLT 1.0, either use a date extension (as suggested by ) or normalize both strings and do a lexicographic compare. Normalization checklist: strip or align fractional seconds, make timezone notation consistent (Z+00:00), and produce a fixed-width canonical form (YYYY-MM-DDThh:mm:ss) before comparing. Important caution: dropping or ignoring timezone offsets can give wrong results when offsets differ — converting offsets to a common UTC value requires arithmetic, so prefer an extension that does that if offsets may vary.

Test with edge cases (different offsets, fractional seconds, missing values) and log the normalized forms before comparison. For long‑term reliability, upgrade to an XSLT 2.0 processor or use a tested extension library rather than ad‑hoc string hacks.

Recommended Answers

All 8 Replies

Are you using XSLT 1.0 or 2.0 ?

Are you using XSLT 1.0 or 2.0 ?

m using 1.0

this is sample

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output indent="yes" method="xml"/>
	<xsl:template match="/">
		<root>
			<xsl:apply-templates select="ABC"/>
		</root>
	</xsl:template>


	<xsl:template match="ABC">

		<xsl:variable name="year" select="substring-before(InputDocument/OrderList/Order/@Modifyts,'-')"/>
		<xsl:variable name="month" select="substring-before(substring-after(InputDocument/OrderList/Order/@Modifyts,concat($year,'-')),'-')"/>
		<xsl:variable name="day" select="substring-before(substring-after(InputDocument/OrderList/Order/@Modifyts,concat($month,'-')),'T')"/>
		<xsl:variable name="time" select="substring(substring-after(InputDocument/OrderList/Order/@Modifyts,concat($day,'T')),1,8)"/>

		<xsl:variable name="oyear" select="substring-before(EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate,'-')"/>
		<xsl:variable name="omonth" select="substring-before(substring-after(EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate,concat($oyear,'-')),'-')"/>
		<xsl:variable name="oday" select="substring-before(substring-after(EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate,concat($omonth,'-')),'T')"/>
		<xsl:variable name="otime" select="substring(substring-after(EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate,concat($oday,'T')),1,8)"/>

		<oderlist>
			<year>
				<xsl:value-of select="$year"/>
			</year>
			<month>
				<xsl:value-of select="$month"/>
			</month>
			<day>
				<xsl:value-of select="$day"/>
			</day>
			<time>
				<xsl:value-of select="$time"/>
			</time>
		</oderlist>
		<order>
			<year>
				<xsl:value-of select="$oyear"/>
			</year>
			<month>
				<xsl:value-of select="$omonth"/>
			</month>
			<day>
				<xsl:value-of select="$oday"/>
			</day>
			<time>
				<xsl:value-of select="$otime"/>
			</time>
		</order>


		<test>
		<compareday>
<xsl:choose>
<xsl:when test="$oday &lt; $day">
<xsl:text>old order</xsl:text>
</xsl:when>
<xsl:when test="$oday &gt; $day">
<xsl:text>new order</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>equale</xsl:text>
</xsl:otherwise>
</xsl:choose>


</compareday>
		</test>
	</xsl:template>
</xsl:stylesheet>

result

<?xml version='1.0' ?>
<root>
  <oderlist>
    <year>2011</year>
    <month>02</month>
    <day>14</day>
    <time>13:53:04</time>
  </oderlist>
  <order>
    <year>2011</year>
    <month>02</month>
    <day>15</day>
    <time>08:12:13</time>
  </order>
  <test>
    <compareday>new order</compareday>
  </test>
</root>

If you're using XSLT 1.0, you can also use the extension functions that are on the site for date manipulation. They've very simple and easy to use. There's a date:difference() function that allows you to easily subtract dates. Then you can just compare the output and print which you want.

If you're using XSLT 1.0, you can also use the extension functions that are on the site for date manipulation. They've very simple and easy to use. There's a date:difference() function that allows you to easily subtract dates. Then you can just compare the output and print which you want.

thanks a lot andrews....that was really kind of you....and your replies were really helpful..thanks a lot man.....

If you're using XSLT 1.0, you can also use the extension functions that are on the site for date manipulation. They've very simple and easy to use. There's a date:difference() function that allows you to easily subtract dates. Then you can just compare the output and print which you want.

btw...have you used cooktop??do u know how the xpath console works?
and can i get the dates using xpath and then compare them?

I'm not familiar with Cooktop as an IDE. I use Stylus Studio and Altova XML Spy for all my needs. As for your questions about XPath to compare them....

In XSLT and XPath 1.0, there is no data type for "date". There's basically strings and numbers. Therefore there are no methods or functions that do any kind of date manipulation. It's just not possible to do directly. That's why in "xml_looser"'s solution he had to break up the string into sections that could be compared like numbers. That's also why people created the EXSLT library. There was a common need to handle dates and various other things that weren't easily done in 1.0. So they created a library of usable components to use as part of their 1.0 solutions.

Once 2.0 came around all this date stuff became simple. "Date" is a real data type in 2.0 and there's a ton of built functions available in 2.0 that could do this in basically one line of code. Unfortunately, in 1.0 almost all date math is hard to do.

So here's another way to do what you want to do. If you go to EXSLT and download the dates package. Look for for the "date.difference.xsl" file in the functions directory. Once you pull this out, you can import into the XSLT below. Look at the implementation of that function on the EXSLT site, and this should make sense.

INPUT

<ABC>
	<InputDocument>
		<OrderList LastOrderHeaderKey="2011013111595948350" LastRecordSet="Y" ReadFromHistory="" TotalOrderList="1">
			<Order DocumentType="0001" EnterpriseCode="XYZ" Modifyts="2011-02-14T13:53:04+00:00" OrderNo="Y100000042"/>
		</OrderList>
	</InputDocument>
	<EnvironmentDocument>
		<Order DocumentType="0001" EnterpriseCode="XYZ" MaximumRecords="5000" OrderNo="Y100000042">
			<OrderDates>
				<OrderDate ActualDate="2011-02-15T08:12:13.5551986Z" DateTypeId="ACK_DATETIME"/>
			</OrderDates>
		</Order>
	</EnvironmentDocument>
</ABC>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="" extension-element-prefixes="date">

	<xsl:import href="functions/difference/date.difference.xsl"/>

	<xsl:template match="/">
		<xsl:variable name="formatDate1" select="substring(ABC/InputDocument/OrderList/Order/@Modifyts, 1, 19)"/>
		<xsl:variable name="formatDate2" select="substring(ABC/EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate, 1, 19)"/>

		<xsl:variable name="getdiff">
			<xsl:call-template name="date:difference">
				<xsl:with-param name="start" select="$formatDate1"/>
				<xsl:with-param name="end" select="$formatDate2"/>
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:choose>
			<xsl:when test="starts-with(string($getdiff), '-')" >
				<xsl:value-of select="ABC/InputDocument/OrderList/Order/@Modifyts" />
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="ABC/EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate" />
			</xsl:otherwise>
		</xsl:choose>

	</xsl:template>


</xsl:stylesheet>

The output is the date which is sooner.

2011-02-15T08:12:13.5551986Z

I'm not familiar with Cooktop as an IDE. I use Stylus Studio and Altova XML Spy for all my needs. As for your questions about XPath to compare them....

In XSLT and XPath 1.0, there is no data type for "date". There's basically strings and numbers. Therefore there are no methods or functions that do any kind of date manipulation. It's just not possible to do directly. That's why in "xml_looser"'s solution he had to break up the string into sections that could be compared like numbers. That's also why people created the EXSLT library. There was a common need to handle dates and various other things that weren't easily done in 1.0. So they created a library of usable components to use as part of their 1.0 solutions.

Once 2.0 came around all this date stuff became simple. "Date" is a real data type in 2.0 and there's a ton of built functions available in 2.0 that could do this in basically one line of code. Unfortunately, in 1.0 almost all date math is hard to do.

So here's another way to do what you want to do. If you go to EXSLT and download the dates package. Look for for the "date.difference.xsl" file in the functions directory. Once you pull this out, you can import into the XSLT below. Look at the implementation of that function on the EXSLT site, and this should make sense.

INPUT

<ABC>
	<InputDocument>
		<OrderList LastOrderHeaderKey="2011013111595948350" LastRecordSet="Y" ReadFromHistory="" TotalOrderList="1">
			<Order DocumentType="0001" EnterpriseCode="XYZ" Modifyts="2011-02-14T13:53:04+00:00" OrderNo="Y100000042"/>
		</OrderList>
	</InputDocument>
	<EnvironmentDocument>
		<Order DocumentType="0001" EnterpriseCode="XYZ" MaximumRecords="5000" OrderNo="Y100000042">
			<OrderDates>
				<OrderDate ActualDate="2011-02-15T08:12:13.5551986Z" DateTypeId="ACK_DATETIME"/>
			</OrderDates>
		</Order>
	</EnvironmentDocument>
</ABC>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="" extension-element-prefixes="date">

	<xsl:import href="functions/difference/date.difference.xsl"/>

	<xsl:template match="/">
		<xsl:variable name="formatDate1" select="substring(ABC/InputDocument/OrderList/Order/@Modifyts, 1, 19)"/>
		<xsl:variable name="formatDate2" select="substring(ABC/EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate, 1, 19)"/>

		<xsl:variable name="getdiff">
			<xsl:call-template name="date:difference">
				<xsl:with-param name="start" select="$formatDate1"/>
				<xsl:with-param name="end" select="$formatDate2"/>
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:choose>
			<xsl:when test="starts-with(string($getdiff), '-')" >
				<xsl:value-of select="ABC/InputDocument/OrderList/Order/@Modifyts" />
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="ABC/EnvironmentDocument/Order/OrderDates/OrderDate/@ActualDate" />
			</xsl:otherwise>
		</xsl:choose>

	</xsl:template>


</xsl:stylesheet>

The output is the date which is sooner.

2011-02-15T08:12:13.5551986Z

Thanks a ton Andrews..your replies where really really helpful....Thanks a lot.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.