Monday, 2 June 2008

XSLT in Java with Oracle Parser

Last week I was struggling with the Oracle XML Parser to get it transforming XML documents with XSL. The thing is that I want to read in my own files into a String and get the results in a String too. In fact the resulting document is not XML since I'm trying to generate Pl/Sql code from an XML document.

As always everything is hard if you don't know how to do it, but if you know then it turns out to be very simple.

First you have to read in your file. For the convenience I assume you know how to do that. In my case: I read in my XML document after I have generated it by parsing an Pl/Sql package from file. But maybe in a later phase I'm going to read it from the database.

Then you have to parse it. That's done as follows:
            XMLDocument xmlDoc;
            String myXmlString = "Not a valid xml";

            DOMParser parser = new DOMParser();
            InputSource inputStream = new InputSource();
            inputStream.setCharacterStream(new StringReader(myXmlString);
            parser.parse(inputStream);
            xmlDoc = parser.getDocument();
Not to hard, is it? You have to do this for both your XML-Document and your XSL-Document.
The code is simply:
  1. Instantiate a parser
  2. Create an inputStream from the input XML String (an xsl-stylesheet is in fact also an xml-document).
  3. Execute the parser
  4. Get a DOM Document (Document Object Model) from the parser.
Then to do the transform I have the following method:
        String transform(XMLDocument xslDoc, XMLDocument xmlDoc) {
        XSLProcessor xslProcessor = new XSLProcessor();
        XSLStylesheet xslt;
        String result = "";
        try {

            xslt = xslProcessor.newXSLStylesheet(xslDoc);

            XMLDocumentFragment fragment;
            xslProcessor.setXSLTVersion(xslProcessor.XSLT20);
            xslProcessor.showWarnings(true);
            xslProcessor.setErrorStream(System.err);
            fragment = xslProcessor.processXSL(xslt, xmlDoc);
            result = fragment.getText();

        } catch (XSLException e) {
            pl(e.toString());
        } catch (IOException e) {
            pl(e.toString());
        }
        return result;
    }
This piece of code does the following:
  1. instantiates a XSL Processor;
  2. create a xslstylesheet from the stylesheet in the xmldocument (that you parsed with the previous piece of code);
  3. set some parameters of the processor: XSL-version, warnings, error-stream to output errors;
  4. process the xslstylesheet, which delivers an xmlfragment (the Oracle XML parser can also output to a URI, but I want to have a string)
  5. at the end get the String document from the xml-fragment
Maybe you'll find that the Xerces parser have more native built-in functionality. I found that although I put in the XSLT2.0 version, most XSLT2.0 functionality does not seem to work in jDeveloper. But I stick with the Oracle parser simply be cause nearly all Oracle product (including jDeveloper and the database) has it. And I might want to run my code in the database. I think I saw Xerces libraries in the SoaSuite as well, but it at this moment the Oracle parser will suffice for me.

To use the Oracle XML parser you need the following imports:
import oracle.xml.parser.v2.XMLDocument;
import oracle.xml.parser.v2.XMLDocumentFragment;
import oracle.xml.parser.v2.XSLException;
import oracle.xml.parser.v2.XSLProcessor;
import oracle.xml.parser.v2.XSLStylesheet;
And of course add the "Oracle XML Parser v2" to your jDeveloper project or add the xmlparserv2.jar and xml.jar files to your class path.

2 comments :

Abu Yaseen said...

Thanks for such valuable information
but there were some comments from some developers that Oracle XML parser is not reliable for example there are some methods that does not exist in the desired calls even though it is called from another class in the same jar file

do u have any idea why the standard Java API does not have support for parsing xml using XSLT 2?
The Amazing JAVA

Martien van den Akker said...

Hi Abu,

I don't know exactly what the problems are. The Oracle XML Parser is extremely important for Oracle because it is the base of all the xml functionality of the database and the AS. It supports (as far as I know) most of the modern XML-features.

However, I found (by trial) that it does not support all xsl2.0 features and for certain specific xsl20 functions you would need extra jars.

I do know that (on contrary what you might expect) the xml parser is maintained by the database group. So features that you as a java/midtier developer might want or need are not supported unless they're needed in the database (like JAXB).

Personally I first try to use the Oracle parser, since it ships with all the Oracle products. If I can't do with it, I fetch Apache Xerces.