The puddle on my XPath

I always tried to stay out of the XML world, but there is no escaping for me now. Currently, I have to deal with the Open Archives Initiative (OAI) Protocol for Metadata Harvesting (PMH). This appears to be a popular protocol to disclose public archives. Technically, it boils down to XML messages with lot’s of different namespaces.To give you an example:

<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
<responseDate>2009-02-26T15:15:22Z</responseDate>
<request verb="GetRecord" metadataPrefix="abc" identifier="AB.abcid1">http://app.archive.nl/oai</request>
<GetRecord>
<record>
<header>
<identifier>AB.abcid1</identifier>
<datestamp>2009-02-24</datestamp>
<setSpec>AB</setSpec>
</header>
<metadata>
<ns1:ns1 xsi:schemaLocation="http://www.archive.nl/abc/1.0 http://www.archive.nl/xsd/abc
/ns1.xsd"xmlns:abc="http://www.archive.nl/abc/1.0">
<ns1:beginTag xml:lang="en-us">
....

Now, how can you select with XPath the content between the metadata tags?

The metadata tag is in the default namespace, so my first guess was to use

[//record/metadata/*]

as XPath. But to my surprise this delivers not the content between the metadata tags. It appears that although the tags record and metadata are in the default namespace, there is no link made with the default namespaceuri.The solution is to create an artificial NamespaceContext with a made up prefix and the default namespaceuri. Let’s take for the sake of the argument ‘oai’ as prefix for the default “http://www.openarchives.org/OAI/2.0/” namespaceuri. The XPath expression would then look like this

[//oai:record/oai:metadata/*].

This delivers the content between the metadata tags.

Every technology has it’s quirks, but I hope not to meet many of them in the XML world. XML appears on the surface simple, but combined with XPath and XSLT you really can find yourself lost. I rather stick to Java were I am in my natural habitat.

Using XMLBeans and Spring-WS for a SOAP webservice client

While the use of SOAP for webservices probably is on the decline, I had to write a client for one. Persuaded by Spring Web Services ( Spring-WS ) that their choice of ‘Contract First’ the right approach is, the second decision was to choose an Object/ XML mapping framework. Because the type of the webservice was SOAP, I knew I had to deal with the XML-language and the chosen mapping framework should not limit the interpretation possibilities of the WSDL-file. The promise of XMLBeans to support theĀ  full XML infoset was for me the decisive argument to use this framework from a rather overwhelming number of options like Castor, JAXB, JiBX, XStream to name a few.

The jump on the Maven2 train last year paid out as I pleasantly found a Maven plugin using xmlbeans to generate the java classes from a xsd file. Always keeping anything related to XML-technology at bay, the creation of a xsd file was the most difficult task for me. But as I experimented with copying parts of the available WSDL-file I quickly was able to construct a xsd file which then could be fed to the maven-plugin to generate the java source.

Packaging the generated code in a seperate Jar I made use of the spring-ws classes to create the client. Defining the beans as like this:

......
<bean id="contactWebServiceGateway"   
   class="nl.aaaa.bbbb.service.webclient.ContactManagementGatewayImpl">
       <property name="databaseName" ref="aDatabase" />
       <property name="authInfo" ref="authInfo" />
       <property name="defaultUri"  value="https://aaa.bbbb.com/soap/1.5/DialogueService" />
       <property name="messageFactory" ref="messageFactory" />
       <property name="marshaller" ref="xmlBeansMarshaller"/>
       <property name="unmarshaller" ref="xmlBeansMarshaller"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller"/>
.........

I have a webservice client where spring-ws and XMLBeans do the heavy lifting of doing marshalling and SOAP-protocol stuff. The only few things there has te done by the client, a subclass of WebServiceGatewaySupport, is to fill the values of the generated xmlbeans and do the actual call to the webservice.

public class ContactManagementGatewayImpl extends WebServiceGatewaySupport implements ContactManagementGateway {
    .......
    public void unsubcribeContact(
    ......
    // the actual call
    Object response = getWebServiceTemplate().
    marshalSendAndReceive(removeContactGroupMembershipDoc
   removeContactGroupMembershipResponseDoc = (RemoveContactGroupMembershipResponseDocument) response;
   }
   .....
}

That is all. In the end it took me longer to decide which Object/ XML mapping framework I should use then writing the client.