Search code examples
javaapache-axisxalan

Applying a xalan java transformation to an axis2 object?


I am tying to get the open source OWL-S API http://on.cs.unibas.ch/owls-api/ to use axis2. I have managed to get the requests sent correctly but when it comes to the response I am having trouble applying a transformation to it. In order to make my question easier to answer I am providing some standalone code which should run without having to import the project. To setup the DOMSource:

String xmlString = "<ns1:countResponse xmlns:ns1=\"http://www.test.de/pill-counter\"><ns1:value>0</ns1:value><ns1:value>0</ns1:value><ns1:value>1</ns1:value><ns1:value>0</ns1:value><ns1:value>0</ns1:value><ns1:value>0</ns1:value></ns1:countResponse>";
    ByteArrayInputStream xmlStream = new ByteArrayInputStream(xmlString.getBytes());
    OMElement test = null;
    try {
        StAXBuilder builder = new StAXOMBuilder(xmlStream);
        test = (OMElement) builder.getDocument().getChildren().next();

    } catch (XMLStreamException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    OMElement documentElement = null;
      try {
        documentElement = AXIOMUtil.stringToOM(DOOMAbstractFactory.getOMFactory(), xmlString);
    } catch (XMLStreamException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }

     SAAJConverterFactory convFactory = (SAAJConverterFactory) FactoryRegistry.getFactory(org.apache.axis2.jaxws.message.factory.SAAJConverterFactory.class);
     SAAJConverter conv = convFactory.getSAAJConverter();


     //Create soap 1.1 message
    SOAPMessage msg = MessageFactory.newInstance().createMessage();
    SOAPPart sp = msg.getSOAPPart();
    SOAPEnvelope se = sp.getEnvelope();
    SOAPBody soapBody = se.getBody();
    javax.xml.soap.SOAPFactory soapFactory = javax.xml.soap.SOAPFactory.newInstance();
    response = conv.toSAAJ(documentElement, soapBody, soapFactory);
    Node root = response;

And now to apply the transformation:

Transformer transformer = null;
    try {
        transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:ns1=\"http://www.test.de/pill-counter\">\n\n\t<xsl:template match=\"/\">\n\t\t<xsl:value-of select=\"sum(*/ns1:value)\" />\n\t</xsl:template>\n</xsl:stylesheet>")));
    } catch (TransformerConfigurationException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    } catch (TransformerFactoryConfigurationError e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    try {
        transformer.transform(new DOMSource(root), new StreamResult(System.out));
    } catch (TransformerException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

The result of running this code is a NullPointerException.

SystemId unknown; Line num.0; Column num.0; java.lang.NullPointerException

I have tried searching for a solution to this problem on Google, the Xalan-j mailing list and on this site with no luck. I have also tried with several other coding approaches and no luck. Any ideas from anyone?

I found another way to get this working by generating the Document from scratch:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    dbf.setValidating(false);
    DocumentBuilder db = null;
    try {
        db = dbf.newDocumentBuilder();
    } catch (ParserConfigurationException e3) {
        // TODO Auto-generated catch block
        e3.printStackTrace();
    }          
    InputSource is = new InputSource(new StringReader(documentElement.toString()));
    Document document = null;
    try{
        document=db.parse(is);
    } catch (SAXException e3) {
        // TODO Auto-generated catch block
        e3.printStackTrace();
    } catch (IOException e3) {
        // TODO Auto-generated catch block
        e3.printStackTrace();
    }

Solution

  • To use the JAXP API on an Axiom tree you don't need to convert it first to SAAJ or DOM. Axiom is able to create a SAXSource that can be passed to JAXP. An example can be found here. That example uses the javax.xml.validation API, but for javax.xml.transform it works the same way.

    Note that the example uses some APIs introduced in recent Axiom versions, but the feature already exists for quite some time. Depending on the Axiom version you are using, the code needs to be adapted to the older API. In particular, instead of calling getSAXSource (which was introduced in 1.2.13), you need to construct an org.apache.axiom.om.impl.jaxp.OMSource object and pass that to JAXP.