Wednesday, August 15, 2012

In this post I will explain you how to convert delimited string to XML fragment/format by using “oraext:create-nodeset-from-delimited-string() function in SOA 11g.

Input Delimited string
E.g.  Vivek,25,Mumbai

In response we should get below xml

<processResponse>
<Name>vivek</Name>
<Age>25</Age>
<Address>Mumbai</Address>
</processResponse>

We need to use one intermediate schema to accomplish this task, so first we will convert delimited string to intermediate schema format and then to final xml format.

create-nodeset-from-delimited-string

To start with this, we need to create a simple composite application.

-          Create a composite and add one Sync BPEL process in it. Use below schema for BPEL

<?xml version="1.0" encoding="UTF-8"?>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified"      targetNamespace="http://xmlns.oracle.com/TestApplication/DelimitedStringToXml/DelimitedStringToXml"
        xmlns="http://www.w3.org/2001/XMLSchema">
 <element name="process">
  <complexType>
   <sequence>
    <element name="input" type="string"/>
   </sequence>
  </complexType>
 </element>
 <element name="processResponse">
  <complexType>
   <sequence>
    <element name="Name" type="string"/>
    <element name="Age" type="string"/>
    <element name="Address" type="string"/>
   </sequence>
  </complexType>
 </element>
</schema>
create-nodeset-from-delimited-string bpel schema

-          Create one intermediate schema

<?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="Customer">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="CustomerInfo" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
create-nodeset-from-delimited-string intermediate schema

-          Now we will convert delimited string to intermediate xml format.  To do this we will use one function “oraext:create-nodeset-from-delimited-string” in assign activity and the operation will be CopyList not Copy.

<assign name="StringToIntermedaiteXMl">
      <bpelx:copyList>
        <bpelx:from expression="oraext:create-nodeset-from-delimited-string('{http://www.example.org}CustomerInfo',bpws:getVariableData('inputVariable','payload','/client:process/client:input'),',')"/>
        <bpelx:to variable="CustomerInfo"
                  query="/ns1:Customer/ns1:CustomerInfo"/>
      </bpelx:copyList>
    </assign>

create-nodeset-from-delimited-string function

-          Now we need to transform intermediate xml format to actual xml format. To do this add one transform.
<assign name="Transform_FinalResult">
      <bpelx:annotation>
        <bpelx:pattern>transformation</bpelx:pattern>
      </bpelx:annotation>
      <copy>
        <from expression="ora:doXSLTransformForDoc('xsl/Transformation_Output.xsl', $CustomerInfo)"/>
        <to variable="outputVariable" part="payload"/>
      </copy>
    </assign>

-          In transform just do the required mapping
                            <xsl:template match="/">
    <client:processResponse>
      <client:Name>
        <xsl:value-of select="/ns0:Customer/ns0:CustomerInfo[1]"/>
      </client:Name>
      <client:Age>
        <xsl:value-of select="/ns0:Customer/ns0:CustomerInfo[2]"/>
      </client:Age>
      <client:Address>
        <xsl:value-of select="/ns0:Customer/ns0:CustomerInfo[3]"/>
      </client:Address>
    </client:processResponse>
    </xsl:template>.

-          Complete Bpel flow

create-nodeset-from-delimited-string bpel

-          Now we are ready to test our bpel peocess. Go to em console and test your bpel process.


Request Test


Response Test

You can download code from here



23 comments :

  1. Hi Vivek,
    This is a great post... Finally a working sample with oraext:create-nodeset-from-delimited-string()...
    Still could not find a way to use it into a XSLT transformation...
    Shame on Oracle that decided not to implement fn:tokenize XPath function, that would make the work so much easier...
    Cheers,
    Vlad

    ReplyDelete
  2. Yes Vlad , as you mentioned fn:tokenize is not available currently.

    "create-nodeset-from-delimited-string" is also available in transform but again you have to follow same steps, first convert delimited string to intermediate format and then to final format.

    Vivek

    ReplyDelete
  3. Tried but instead of the nodes I got this...

    <tns:val>oracle.xml.parser.v2.XMLNodeList@246be4</tns:val>

    Can you please post a sample with XSLT?

    Cheers,
    Vlad

    ReplyDelete
    Replies
    1. Vlad,

      Sample code is attached in the post , you can download it and check the transform.

      Vivek

      Delete
  4. Hi Vivek,
    The sample code doesn't have create-nodeset-from-delimited-string IN the XSLT transformation.
    I'm looking for a way to use create-nodeset-from-delimited-string in a XSLT transf, at the moment, I don't think it's possible.
    Cheers,
    Vlad

    ReplyDelete
    Replies
    1. Vlad,

      I never tried "create-nodeset-from-delimited-string" function inside XSLT. I will try to create one sample and will share with you.

      Vivek

      Delete
    2. Vlad,

      You can not use this function inside transform. This is Bug (14548762). Hope Oracle will come up with solution in next release.

      Vivek

      Delete
  5. Nice Post, helped me a lot

    Thanks

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Hi, I tried your example but for some reason, when create the nodeset from the delimited string, the result complex object is not the original Customer, it renames the child CustomerInfo nodes to Customer, so I have

    Customer
    Customer
    Customer c1 /Customer
    Customer c2 /Customer
    Customer c3 /Customer
    /Customer
    /Customer



    any idea what i am doing wrong?

    thanks for the post btw

    ReplyDelete
    Replies
    1. Hi Rene,

      Make sure you are using correct schema and mapping nodeset function to CustomerInfo not to Customer element of the schema.

      Thanks
      Vivek Garg

      Delete
  8. Hi Vivek,
    Im using the below code and it works fine., But it ommiting all the empty fields.., Is there any way to include the empty tags also,






    And my input is ,
    C|2004|CL009|007|||101
    And my Current Output is,
    C
    2004
    CL009
    007
    101

    But i want output like below,
    C
    2004
    CL009
    007


    101

    Can you please help in this.??

    ReplyDelete
  9. My Current Output..,
    (Result) C (/Result)
    (Result) 2004 (/Result)
    (Result) CL009 (/Result)
    (Result) 007 (/Result)
    (Result) 101 (/Result)

    Expected output:
    (Result) C (/Result)
    (Result)2004 (/Result)
    (Result) CL009 (/Result)
    (Result) 007 (/Result)
    (Result/)
    (Result/)
    (Result) 101 (/Result)

    ReplyDelete
    Replies
    1. Hi Praba,

      This should work. Please send me your code to my id (gargvivek2008@gmail.com). I will look over it.

      Thanks
      Vivek Garg

      Delete
    2. was there any update on this? i am experiencing the same issue..

      input string is "x;xx;xxx;;xxxxx"
      with delimiter ";"
      and instead of "x","xx","xxx","","xxxxx"
      i receive ""x","xx","xxx","xxxxx"

      Delete
    3. I tried but I also got the same response. Seems like this function does not allow null values.

      Delete
  10. Hi Vivek,
    Is it possible to create node-set from more than on delimited string?
    Ex:
    1,2,3
    x,y,z
    1990,1991,1992 to

    1
    x
    1990


    2
    y
    1991


    3
    z
    1992

    ReplyDelete
    Replies
    1. We can use only one delimited string in this function.

      Delete
    2. dhanasekaran ShanmuganandamMay 9, 2014 at 5:19 PM

      Thanks for the reply ya.. I think I can do it by for each/Repeat Until and substring functions in BPEL. Lemme try that..

      Delete
  11. Hi Vivek, I am trying to do countNodes on the result from the create-nodeset-from-delimited-string function but this does not seem to work

    please see code below

    oraext:create-nodeset-from-delimited-string('{http://xmlns.oracle.com/TestNodeSet_jws/TestNodeSet/TestNodeSet} innerElement',bpws:getVariableData('inputVariable','payload','/client:process/client:input'),';')

    ora:countNodes('OuterElement','','/client:Output/client:innerElement')

    ReplyDelete
    Replies
    1. Hi,

      Please try with count function , like count(bpws:getVariableData('inputVariable','payload','/client:process/client:input'))

      Vivek Garg

      Delete
  12. Helped me solve one of my requirement. Glad that you shared :)

    ReplyDelete