# Using XQuery Within Script Functions

You can write an ECMAScript function that contains XQuery instead of script, then call that function from an XQuery map or Java code. The function may contain only the XQuery expression.

A script function that contains XQuery must be annotated with a language:body annotation that indicates that the language of the function's body is XQuery. For example, the following function contains an XQuery function that selects the zip elements from the incoming XML, then adds them as child elements of a newly created element, zip-list.

    /**
     * @language:body type="XQuery"
     */
    function selectZipsNewDoc(xml)
    {
        declare namespace xq="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress"
        declare namespace ns="http://www.openuri.org/"
        let $e := $xml/ns:selectZipsResponse/xq:employees
        return
            <zip-list>
                {for $z in $e/xq:employee/xq:address/xq:zip
                return $z}
            </zip-list>
    }

Briefly, here's what this function does:

- Takes a single parameter for XML passed in from an XQuery map.
- Declares two namespaces that are used in the XQuery expression. The namespace represented by the xq prefix belongs with the XML containing employee information; the namespace represented by the ns prefix belongs with the XML representing the web service operation (selectZipsResponse).
- Declares an "e" variable to represent the employees root element.
- Constructs a zip-list element for use in the return value.
- Declares a "z" variable to represent the zip elements, looping through and returning the zip elements as children of the zip-list element.

An XQuery map that calls this function might look like this:

    /**
     * @common:operation
     * @jws:return-xml xquery::
     *   declare namespace ns0="http://www.openuri.org/"
     *   declare namespace ns1="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress"
     *   <ns1:employees>
     *     {xmlBeans.xquery.EmpQueryScripts.selectZipsNewDoc($input)}
     *   </ns1:employees>
     *   ::
     * schema-element="ns0:employees"
     */
    public XmlObject selectZips(XmlObject xml)
    {
        return xml;
    }

Notice that the call to the script function (in bold) must be nested within another element. With the map and script, the selectZips method's return value looks like this:

    <con:employees xmlns:con="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">
        <zip-list>
            <ns0:zip xmlns:ns0="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">98115</ns0:zip>
            <ns1:zip xmlns:ns1="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">98052</ns1:zip>
            <ns2:zip xmlns:ns2="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">97125</ns2:zip>
            <ns3:zip xmlns:ns3="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">97103</ns3:zip>
            <ns4:zip xmlns:ns4="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">98115</ns4:zip>
            <ns5:zip xmlns:ns5="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress">98052</ns5:zip>
        </zip-list>
    </con:employees>

Related Topics

None.