MalformedURLException when one XSLT imports another

I am having a problem where one XSLT file imports another, causing my application to throw a MalformedURLException. The import statement in main.xsl looks like this:

<xsl:import href="transformCommon.xsl"/>

the file transformCommon.xsl is in the same folder as main.xsl. The code that attemts to load it looks like this:

private void loadXSLTFiles(String xsltFile)
{
    TransformerFactory transformFactory = TransformerFactory.newInstance();  

    //tell the location of all of import file 
    transformFactory.setURIResolver(new ClassPathURIResolver());

    Templates cache=null;

    //cache XSLT source file for transformation reuse
    InputStream is = this.getClass().getClassLoader().getResourceAsStream(xsltFile);
    javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(is);

    try
    {
        cache = transformFactory.newTemplates(xsltSource);
    }
    catch (TransformerConfigurationException domException)
    {
        LOG.logError("XSLT initialization error has occurred: " + domException.getMessage());
    }
    ...

The stack trace is:

Caused by: java.net.MalformedURLException
    at java.net.URL.(URL.java:602)
    at java.net.URL.(URL.java:465)
    at java.net.URL.(URL.java:414)
    at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.apache.xalan.templates.StylesheetRootProxy.(Unknown Source)
    ... 59 more

I'm not sure why I get this error. When I remove the import from main.xsl, everything works fine. Of course, removing it is not an option as the whole point of this was to move common functions to a separate XSLT.

What's also interesting is that only my workstation seems to have this problem. The developer who initially wrote this code says he has no problems with it. I'm using RAD 7.5. Does anyone know how this problem could come up, on a workstation-by-workstation basis?

Upvotes: 3

Views: 3848

Answers (1)

Ian Roberts
Ian Roberts

Reputation: 122414

In order to be able to resolve relative URLs in the stylesheet (including imports) the Source from which you create the Templates needs to have a "system ID" (i.e. the URL of the .xsl file).

Instead of

//tell the location of all of import file 
transformFactory.setURIResolver(new ClassPathURIResolver());

//cache XSLT source file for transformation reuse
InputStream is = this.getClass().getClassLoader().getResourceAsStream(xsltFile);
javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(is);

try this:

URL xsltURL = this.getClass().getClassLoader().getResource(xsltFile);
Source xsltSource = new StreamSource(xsltURL.openStream(),
                                     xsltURL.toExternalForm());

(openStream can throw IOException so you'll either need to add that to your throws or wrap the whole thing in a try/catch).

Upvotes: 5

Related Questions