Disclaimer : This blog space does not necessarily reflect my views/ideas on the technology and beyond doubt, never reflects the views of my employer.
Showing posts with label XPath. Show all posts
Showing posts with label XPath. Show all posts

Saturday, November 15, 2008

Calculating difference between 2 datetime values in Oracle BPEL

If you are require to use lots of datetime values, then you may also need to manipulate those different datetime values. Manipulating XPath 2.0 functions may be a problem. For this, You may refer to blogs by Ramkumar Menon and Antony Reynolds.

I'm using XPath 2.0 functions to get date and time in BPEL Process. You can get more information about XPath 2.0 here. Below is the example I have created based on Ramkumar's blog to calculate the duration between two datetime values in Oracle BPEL.


First create two schemas,

input.xsd

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org"
targetNamespace="http://www.example.org"
elementFormDefault="qualified">
<xsd:element name="input">
<xsd:annotation>
<xsd:documentation>
A sample element
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="date1" type="xsd:dateTime"/>
<xsd:element name="date2" type="xsd:dateTime"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

and output.xsd

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org"
targetNamespace="http://www.example.org"
elementFormDefault="qualified">
<xsd:element name="output">
<xsd:annotation>
<xsd:documentation>
A sample element
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="duration" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>


As schemas are ready, we will create the BPEL process now.

In BPEL Process, the namespace for XPath 2.0 is declared like

xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"

also xmlns:ns1="http://www.example.org"


and the the this xp20 functions can be used as below to extract the datetime values.

  • xp20:current-dateTime() - returns a dateTime element that has the current date and time as formatted above. (e.g. 2008-11-15T11:32:28.256). I'm using this function and I am to calculate difference for variable holding this value.
  • xp20:current-date() - returns a date element that has the current date as formatted above without the time portion.
  • xp20:current-time() - returns a time element that has the current time formatted as above without the date portion.

In BPEL Process, create two variables,

<variable name="inputdate" element="ns1:input"/>
<variable name="outputValue" element="ns1:output"/>

Create the transformation activity,

<assign name="Transform_1">
<bpelx:annotation>
<bpelx:pattern>transformation</bpelx:pattern>
</bpelx:annotation>
<copy>
<from expression="ora:processXSLT('Transformation_1.xsl',bpws:getVariableData('inputdate'))"/>
<to variable="outputValue"/>
</copy>
</assign>


Let's look at how the XSL file is to be designed. We are creating the template "timeDifference" and using the same to find the time difference.

In the starting of the XSL file, definition of the source and target XSD.

<?xml version="1.0" encoding="UTF-8" ?>
<?oracle-xsl-mapper
<!-- SPECIFICATION OF MAP SOURCES AND TARGETS, DO NOT MODIFY. -->
<mapSources>
<source type="XSD">
<schema location="input.xsd"/>
<rootElement name="input" namespace="http://www.example.org"/>
</source>
</mapSources>
<mapTargets>
<target type="XSD">
<schema location="output.xsd"/>
<rootElement name="output" namespace="http://www.example.org"/>
</target>
</mapTargets>


XSL stylesheet version to be changed to 2.0 and looks like

<xsl:stylesheet version="2.0"

...
xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://www.example.org"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xsl ns0 xsd ora ...">

In next phase define the template and use it to calculate the difference as below


<xsl:template match="/"> <!-- Suggests that template is in this file only -->
<ns0:output>
<ns0:duration>
<xsl:call-template name="timeDifference">
<xsl:with-param name="date1" select="/ns0:input/ns0:date1"/>
<xsl:with-param name="date2" select="/ns0:input/ns0:date2"/>
</xsl:call-template>
</ns0:duration>
</ns0:output>
</xsl:template>

<xsl:template name="timeDifference">
<xsl:param name="date1"/>
<xsl:param name="date2"/>
<xsl:value-of select="(xsd:dateTime($date1) - xsd:dateTime($date2))"/>
</xsl:template>
</xsl:stylesheet>

If you inputs are
2008-11-15T11:32:28.256
2008-11-15T11:33:32.256

the output will be
T1M4.0S



Hope this helps. Let me know if you are facing any issues.

Cheers

Nirav

Wednesday, September 24, 2008

Revisiting XPath

Was reading w3schools.com in order to learn more concepts of XPath and thought to create a post as extracting information from tutorial. Here is some ready information on XPath.

What is XPath?
  • XPath is a syntax for defining parts of an XML document
  • XPath uses path expressions to navigate in XML documents
  • XPath contains a library of standard functions
  • XPath is a major element in XSLT
  • XPath is a W3C Standard

or XPath is a language for finding information in an XML document. The XPath language is based on a tree representation of the XML document, and provides the ability to navigate around the tree through elements and attributes in an XML document by a variety of criteria.

In addition, XPath may be used to compute values (strings, numbers, or boolean values) from the content of an XML document. The current version of the language is XPath 2.0.


XPath became a W3C Recommendation 16. November 1999.


XPath was designed to be used by XSLT, XPointer and other XML parsing software.
In XPath, there are seven kinds of nodes: element, attribute, text, namespace, processing-instruction, comment, and document (root) nodes.


If we have books.xml as below :
<?xml version="1.0" encoding="ISO-8859-1"?><bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book><book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book><book category="WEB">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book><book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book></bookstore>

If you carefully observer first book has title Everydat Itralian, 2nd Book is Harry Potter. To extract this values create HTML page in the similar folder where you have created above books.html as below :
<html> <body>
<script type="text/javascript">
function loadXMLDoc(fname)
{
var xmlDoc;
// code for IE
if (window.ActiveXObject)
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation
&& document.implementation.createDocument)
{
xmlDoc=document.implementation.createDocument("","",null);
}
else
{
alert('Your browser cannot handle this script');
}
xmlDoc.async=false;
xmlDoc.load(fname);
return(xmlDoc);
}
xml=loadXMLDoc("books.xml");
path="/bookstore/book[2]/title";

// code for IE
if (window.ActiveXObject)
{
xml.setProperty("SelectionLanguage","XPath");
var nodes=xml.selectNodes(path);
for (i=0;i<nodes.length;i++)
{
document.write(nodes[i].childNodes[0].nodeValue);
document.write("<br />");
}
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument)
{
var nodes=document.evaluate(path, xml, null, XPathResult.ANY_TYPE,null);
var result=nodes.iterateNext();
while (result)
{
document.write(result.childNodes[0].nodeValue);
document.write("<br />");
result=nodes.iterateNext();
}
}
</script>
</body> </html>

Open the html file in browser and check the output. It should be "Everyday Italian".
Please observe the following line in HTML page.
path="/bookstore/book[1]/title";
This is pointing to specific book tag in the xml file. book[1] points to the first book tag in the xml document. change the value from book[1] to book[2] and you will get output Harry Potter instead Everyday Italian.

Also, observe the following line in HTML page
var nodes=xml.selectNodes(path);
Check the highlighted lines in HTML page and this is self-explanatory.

Hope this XPath article helps. Hope to write mroe about XPath nodes in detail in near future.
Many thanks to w3schools.com

Cheers
Nirav