Validating Update Requests

Suppose now our system receives a message containing an address change request (tc=181 in ACORD parlance). Before even processing it, however, we want to make sure the message is semantically valid (not just valid in terms of the ACORD standards); in particular we want to ensure that:

  • the person exists
  • the old address exists
  • the new ZIP code is valid
  • the new ZIP code corresponds to the new state

The XQuery implementing such validation is shown here (click this link to open the XQuery document):

declare namespace tx="http://ACORD.org/Standards/Life/2";

import module namespace example = "http://www.datadirect.com/xquery/examples" at "acord_verbs.xquery";

(: Example of business validation on an "Address Change" request :)
let $request := doc("181-1.xml")
return example:validate-181($request/tx:TXLife/tx:TXLifeRequest)

As you can see in acord_verbs.xquery, example:validate-181() fetches data from two relational tables (ACORD_PERSON and ACORD_ADDRESS), performs the various checks, and returns either an empty result (no errors; success), or a message describing the error condition (failure). The first part of the function is particularly interesting, as it is responsible for implementing the actual business validation rules:

declare function example:validate-181($request as element(tx:TXLifeRequest)) as element(tx:TXLifeResponse)? {
    let $party := $request/tx:OLifE/tx:Party[@id eq $request/@PrimaryObjectID]
    let $key := xs:string($party/tx:PartyKey)
    let $person := collection("ACORD_PERSON")/ACORD_PERSON[PartyKey eq $key]
    let $oldAddress := $party/tx:Address[@DataRep eq "Removed"]
    let $newAddress := $party/tx:Address[@DataRep eq "Full"]
    let $row := collection("ACORD_ADDRESS")/ACORD_ADDRESS
            [OwnerKey eq $key]
            [AddressTypeCode eq xs:integer($oldAddress/tx:AddressTypeCode/@tc)]
            [Line1 eq $oldAddress/tx:Line1]
            [City eq $oldAddress/tx:City]
            (: AddressState is nullable :)
            [AddressState eq $oldAddress/tx:AddressState
             or
             fn:empty(AddressState) and fn:empty($oldAddress/tx:AddressState)]
            [Zip eq $oldAddress/tx:Zip]
            [AddressCountry eq $oldAddress/tx:AddressCountry]
    let $rowValid := fn:count($row) eq 1
    let $zipState :=
        if ( $newAddress/tx:AddressCountry eq "USA" )
        then
            example:getZipInfo($newAddress/tx:Zip)
        else
            ()

Validation of the ZIP code, when "AddressCountry" is "USA" is delegated to the example:getZipInfo() function, which in turns delegates validation to a third party public Web Service, published by http://www.webservicemart.com (http://www.webservicemart.com/uszip.asmx):

declare function example:getZipInfo($zipCode as xs:string) as element()? {
    let $response :=
        ddtek:wscall(
            <ddtek:location address="http://www.webservicemart.com/uszip.asmx"
                            soapaction="http://webservicemart.com/ws/ValidateZip"/>,

            <ws:ValidateZip>
                <ws:ZipCode>{$zipCode}</ws:ZipCode>
            </ws:ValidateZip>
        )/ws:ValidateZipResponse/ws:ValidateZipResult
    return
        (: because the webservice returns the result as text (not xml) wrapped
           in a ValidateZipResult node we have to parse the content :)

        ddtek:parse($response/text())/*
};

Thanks to the ddtek:wscall() function, invoking external Web Service from a DataDirect XQuery™ is extremely simple, as you can see.


What's Next

Now that you see how to use DataDirect XQuery™ to validate data, go to Updating a Relational Database to learn how to update relational data with DataDirect XQuery™.

DataDirect XQuery FAQ

This informative DataDirect XQuery® FAQ answers frequently-asked questions about DataDirect XQuery® , including questions about performance, scalability, use-cases, resources, and more.

If you're more of a hands-on learner, then download a free copy and start exploring DataDirect XQuery® today!

New Case Study

Gevity produces sales proposals in real time using DataDirect XQuery® . See how Gevity uses DataDirect XQuery® to combine Web service data from SalesForce.com with relational data in Oracle in a pricing engine for HR management.