Contact Us 1-800-596-4880

XQuery Support

The XQuery Module gives users the ability to perform XQuery transformations on XML messages in Mule. This works in a very similar way to the XSLT Transformer shipped with Mule.

Configuration

To use the XQuery transformer you need to add it to your Mule Xml configuration

<mxml:xquery-transformer name="xquery">

        <mxml:context-property key="title" value="#[header:ListingTitle]"/>
        <mxml:context-property key="rating" value="#[header:ListingRating]"/>

        <mxml:xquery-text>
           <![CDATA[
                declare variable $document external;
                declare variable $title external;
                declare variable $rating external;

                <cd-listings title='{$title}' rating='{$rating}'> {
                    for $cd in $document/catalog/cd
                    return <cd-title>{data($cd/title)}</cd-title>
                } </cd-listings>
            ]]>
        </mxml:xquery-text>

    </mxml:xquery-transformer>

Here we are configuring a transformer using in-line XQuery expressions.

We also define 2 <context-property> elements -

<mxml:context-property key="title" value="#[header:ListingTitle]"/>
<mxml:context-property key="rating" value="#[header:ListingRating]"/>

These properties are pulled from the current message and made available in the XQuery context so that they can be referenced in your XQuery statements. These can be object references or you can use Mule Expressions to get information from the current message.

Example

Now your configured XQuery transformer can be referenced by an endpoint. In the following example, you can drop and XML file into a directory on the local machine (see the inbound file endpoint) and the result will be written to System.out.

The test data looks like -

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
     ...
</catalog>

The result written to System.out will look like -

<cd-listings title="MyList" rating="6">
    <cd-title>Empire Burlesque</cd-title>
    <cd-title>Hide your heart</cd-title>
     ...
</cd-listings>

The full configuration for this examples looks like -

<mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:mxml="http://www.mulesoft.org/schema/mule/xml"
      xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
      xmlns:stdio="http://www.mulesoft.org/schema/mule/stdio"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
      http://www.mulesoft.org/schema/mule/stdio http://www.mulesoft.org/schema/mule/stdio/3.0/mule-stdio.xsd
      http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.0/mule-vm.xsd
      http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/3.0/mule-xml.xsd
       http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.0/mule.xsd">

    <mxml:xquery-transformer name="xquery">

        <mxml:context-property key="title" value="#[header:ListingTitle]"/>
        <mxml:context-property key="rating" value="#[header:ListingRating]"/>

        <mxml:xquery-text>
           <![CDATA[
                declare variable $document external;
                declare variable $title external;
                declare variable $rating external;

                <cd-listings title='{$title}' rating='{$rating}'> {
                    for $cd in $document/catalog/cd
                    return <cd-title>{data($cd/title)}</cd-title>
                } </cd-listings>
            ]]>
        </mxml:xquery-text>

    </mxml:xquery-transformer>

    <model name="main">
    <service name="Echo">
        <inbound>
            <!-- this endpoint is used by the functional test -->
            <vm:inbound-endpoint path="test.in" transformer-refs="xquery" synchronous="true"/>
        </inbound>

        <echo-component/>

        <outbound>
            <multicasting-router>
                <vm:outbound-endpoint path="test.out"/>
                <stdio:outbound-endpoint system="OUT"/>
            </multicasting-router>
        </outbound>
    </service>
    </model>

</mule>

Testing it

This can be tested using the following functional test -

public class XQueryFunctionalTestCase extends FunctionalTestCase
{
    protected String getConfigResources()
    {
        //Our Mule configuration file
        return "org/mule/test/integration/xml/xquery-functional-test.xml";
    }

    public void testMessageTransform() throws Exception
    {
        //We're using Xml Unit to compare results
        //Ignore whitespace and comments
        XMLUnit.setIgnoreWhitespace(true);
        XMLUnit.setIgnoreComments(true);

        //Read in src and result data
        String srcData = IOUtils.getResourceAsString("cd-catalog.xml", getClass());
        String resultData = IOUtils.getResourceAsString("cd-catalog-result-with-params.xml", getClass());

        //Create a new Mule Client
        MuleClient client = new MuleClient(muleContext);

        //These are the message roperties that will get passed into the XQuery context
        Map props = new HashMap();
        props.put("ListTitle", "MyList");
        props.put("ListRating", new Integer(6));

        //Invoke the service
        MuleMessage message = client.send("vm://test.in", srcData, props);
        assertNotNull(message);
        assertNull(message.getExceptionPayload());
        //Compare results
        assertTrue(XMLUnit.compareXML(message.getPayloadAsString(), resultData).similar());
    }
}