Thursday, August 10, 2006

Manipulating XML payload

Introduction

When you are using BPEL 10.1.2 and want to replace values in an XML payload. There are a few possibilities:

  • Using assign with from and to tags. In the to-tag you can add a XPATH queury. A disadvantage is that the XPATH query in the to-tag can not be dynamic.
  • Using XSLT stylesheet. This use more CPU intensive and additional files are needed to format the XML input to the desired output.
  • Using and expression function like addChildNode(), appendChildNode(). These functions are deprecated.
So what is the best way to handle XML? Thanks to murugac for his answer on the BPEL forum. I copied it to my blog to extract the reusable text.

Please don't use the addChildNode() function, this function is going to deprecated, instead use the new bpel extension insert/append (bpelx:append):

Syntax:
<bpel:assign>
<bpelx:append>
<bpelx:from ... />
<bpelx:to ... />
</bpelx:append>
</bpel:assign>

The from-spec within <append> yields a single node or a node list. (Please note: the from-spec of <bpel:copy> still MUST yield ONLY one node.) The node list will be appended as child nodes to the target node specified by to-spec. If the from-spec yields zero node, "bpel:selectionFailure" fault will be generated.

The to-spec MUST yield one single L-Value element node. Otherwise, "bpel:selectionFailure" fault will be generated. The to-spec cannot refer to a partnerLink.

See: appendChild (org.w3c.dom.Node)

Example: (XSD details at end of the document)

Consolidating multiple bills of material into one single bill of material by appending multiple "b:part" for one BOM to "b:parts" the consolidated BOM.
-----------------------
<bpel:assign>
<bpelx:append>
<from variable="billOfMaterialVar"
query="/b:bom/b:parts/b:part" />
<to variable="consolidatedBillOfMaterialVar"
query="/b:bom/b:parts" />
</bpelx:append>
</bpel:assign>
-----------------------

2. Insert
2.1 insertBefore
Syntax:
<bpel:assign>
<bpelx:insertBefore>
<bpelx:from ... />
<bpelx:to ... />
</bpelx:insertBefore>
</bpel:assign>

The restriction and semantics of from-spec under insertBefore is similar to those in the case of <bpelx:append>.

The to-spec under <insertBefore> MUST points to one or more single L-Value nodes. If more than one nodes are returned, the first node will be used as the reference node. The reference node MUST be an element node. The parent of the reference node MUST be an element node also. Otherwise, "bpel:selectionFailure" fault will be generated. The to-spec cannot refer to a partnerLink.

The node list generated by the from-spec will be inserted before the reference node.

See: insertBefore(org.w3c.dom.Node,%20org.w3c.dom.Node)

Example: (XSD details at end of the document)

Say before the execution of <insertBefore>, the value of "addrVar" is:
----------------------
<a:usAddress>
<a:state>CA</a:state>
<a:zipcode>94065</a:zipcode>
</a:usAddress>
----------------------

After the execution of the following:
----------------------
<bpel:assign>
<bpelx:insertBefore>
<from>
<a:city>Redwood Shore></a:city>
</from>
<to "addrVar" query="/a:usAddress/a:state" />
</bpelx:insertBefore>
</bpel:assign>
----------------------

The value of "addrVar" becomes:
----------------------
<a:usAddress>
<a:city>Redwood Shore</a:city>
<a:state>CA</a:state>
<a:zipcode>94065</a:zipcode>
</a:usAddress>
----------------------


2.2 insertAfter
Syntax:
<bpel:assign>
<bpelx:insertAfter>
<bpelx:from ... />
<bpelx:to ... />
</bpelx:insertAfter>
</bpel:assign>

<insertAfter> is very similar to <insertBefore>. Except:

If more than one L-Value nodes are returned by the to-spec, the last node will be used as the reference node.
Instead of inserting nodes "before" the reference node, the source nodes will be inserted after the "reference" node.

This operation can also be considered a macro of conditional-switch + (append or insertBefore).


Example: (XSD details at end of the document)

Say before the execution of <insertAfter>, the value of "addrVar" is:
----------------------
<a:usAddress>
<a:addressLine>500 Oracle Parkway</a:addressLine>
<a:state>CA</a:state>
<a:zipcode>94065</a:zipcode>
</a:usAddress>
----------------------

After the execution of the following:
----------------------
<bpel:assign>
<bpelx:insertAfter>
<from>
<a:addressLine>Mailstop 1op6</a:addressLine>
</from>
<to "addrVar" query="/a:usAddress/a:addressLine[1]" />
</bpelx:insertAfter>
</bpel:assign>
----------------------

The value of "addrVar" becomes:
----------------------
<a:usAddress>
<a:addressLine>500 Oracle Parkway</a:addressLine>
<a:addressLine>Mailstop 1op6</a:addressLine>
<a:state>CA</a:state>
<a:zipcode>94065</a:zipcode>
</a:usAddress>
----------------------

Post a Comment