Comments? Feedback?

This wiki does not yet support public comments (a limitation of Google Sites), so we encourage you to post your comments either:

On Twitter by responding to @orbeon.

On our community mailing list: subscribe sending an email to ops-users-subscribe@ow2.org (content of subject/body doesn't matter), you'll get a response with the email to use to send your message to the community mailing list.

Recent site activity

How-to guides‎ > ‎XForms Logic‎ > ‎

Call a service returning XML with an incorrect content type


The problem 

You are calling a service that returns XML with an XForms submission, but the service incorrectly advertises the result with a non-XML content type, such as text/plain. Even if the content type is incorrect, the body contains proper XML, which you'd like to handle as if it was returned with an XML content type, such as application/xml.

The solution 

Fix the service. Now, if you really can't, what follows is a workaround. However keep in mind that this will make your code more verbose and harder to understand, so again, the right way address this is to fix the service and get it to return a proper XML content type.

When the service is called as its result doesn't have an XML content type, the submission fails with an xforms-submit-error. You can listen to that event, and use event('response-body') to access the body of the result. This will be a string containing the unparsed XML you're interested in. You can parse that string with the saxon:parse() function and use <xforms:insert> to replace the content of an instance with the parsed XML.

But what if, after all, the service really failed and doesn't return XML? In that case running saxon:parse() on non-XML text would throw an exception which would become visible to your users. So you only want to run saxon:parse() after you're sure that the returned text is indeed XML. You can do so by storing it in a node, which you validate with a <xforms:bind type="xxforms:xml"/>. You can then use xxforms:valid() to check on the validity of that node, and only do the parsing if the text is indeed XML. Here is the important part of the source, and see below for a link to a stand-alone example.


<!-- Instance holding the result from the submission -->
<xforms:instance id="countries"><initial/></xforms:instance>

<!-- Instance with the text from the service, if not returned with an XML content type -->
<xforms:instance id="unparsed-xml"><unparsed-xml/></xforms:instance>
<xforms:bind ref="instance('unparsed-xml')" type="xxforms:xml"/>

<!-- Call a service that might return XML with the incorrect content type -->
<xforms:submission id="get-countries" ref="instance('countries')"
                   resource="http://dl.dropbox.com/u/6900/resources/20110620-countries.txt"
                   serialization="none" method="get" replace="instance"/>

<xforms:action ev:event="xforms-submit-error" ev:observer="get-countries">
    <!-- Store text we got back from service -->
    <xforms:setvalue ref="instance('unparsed-xml')" value="event('response-body')"/>
    <!-- Revalidate so the 'type' constraint is reapplied -->
    <xforms:revalidate/>
    <!-- If we got XML back, parse it and store it in 'countries' -->
    <xforms:insert if="xxforms:valid(instance('unparsed-xml'))"
        nodeset="instance('countries')" origin="saxon:parse(instance('unparsed-xml'))"/>
</xforms:action>


Get the source