Thursday, September 15, 2011

dateTime duration with XSLT in SOA 11g

This tiny post reminds me the exact reason why I started this blog. I want to collect the things I learned using SOA.

It took me a long time to figure out this tidbit with XSLT before, but I just spent half a day to re-figure it out again. 

In my XSLT I need to calculate the duration based on two dateTime fields. So I used this expression:
    <xsl:variable name="dur">
      <xsl:value-of select="xsd:dateTime($endDt)-xsd:dateTime($stDt)"/>
    </xsl:variable>

However, with JDEV 11g, the default XSLT stylesheet version is "1.0". The above expression doesn't work with "1.0". I have to change the version to "2.0". That's all. With that, "dur" will have a value like "PT2H5M". Then you can maniplate it.

Now I have recorded it here, so I don't have spend another 5 hours to "re-discover" it next time.

Tuesday, September 13, 2011

Tweaking auto-generated XSLT may result in "Element not found" error

I have a JDEV generated XSLT like below.

<?xml version="1.0" encoding="UTF-8" ?>
<?oracle-xsl-mapper
  <!-- SPECIFICATION OF MAP SOURCES AND TARGETS, DO NOT MODIFY. -->
  <mapSources>
    <source type="WSDL">
      <schema location="../BPELProcess1.wsdl"/>
      <rootElement name="process" namespace="http://xmlns.oracle.com/test/testImdXform/BPELProcess1"/>
    </source>
  </mapSources>
  <mapTargets>
    <target type="XSD">
      <schema location="../xsd/D1_InitialLoadIMD.xsd"/>
      <rootElement name="D1-InitialLoadIMD" namespace="http://oracle.com/D1-InitialLoadIMD.xsd"/>
    </target>
  </mapTargets>
  <!-- GENERATED BY ORACLE XSL MAPPER 11.1.1.5.0(build 110418.1550.0174) AT [TUE SEP 13 15:55:59 MST 2011]. -->
?>
<xsl:stylesheet version="1.0"
...
xmlns:ns1="http://oracle.com/D1-InitialLoadIMD.xsd"
...>
  <xsl:template match="/">
    <ns1:D1-InitialLoadIMD>
      <ns1:version>
        <xsl:value-of select="/client:process/client:input"/>
      </ns1:version>
    </ns1:D1-InitialLoadIMD>
  </xsl:template>
</xsl:stylesheet>

Looking at the file, it is very tempting to replace "ns1" with default namespace, i.e. xmlns="http://oracle.com/D1-InitialLoadIMD.xsd", then get rid of "ns1" from the file.

The result may look clean.

<xsl:stylesheet version="1.0"
...
xmlns="http://oracle.com/D1-InitialLoadIMD.xsd"
...>
  <xsl:template match="/">
    <D1-InitialLoadIMD>
      <version>
        <xsl:value-of select="/client:process/client:input"/>
      </version>
    </D1-InitialLoadIMD>
  </xsl:template>
</xsl:stylesheet>

However, this is a fatal attraction. Even though the content should be technically equivalent, but I got an  "Line Number:(13) : Error: "D1-InitialLoadIMD" Element not Found in Target Schema".

It cost me a few hours to sort it out. The morale of the story, be careful when you mess up the namespace with the auto-generated XSLT.