1

I need to replace a certain text in a XML file before giving it to the XSL-Transformer. It's the DTD-URL in the DOCTYPE tag. It points to a webserver, but I want it to be usable offline, so I want to change it to a URL pointing to a local file.

However I mustn't edit the original XML directly. I thought of reading the file into a string, use String.replaceAll() on the text and save it into another file, which I pass to the Transformer. I already tried it, but it's really slow; the file I'm using has a size of ca. 500kiB.

Is there any better (=faster) way to accomplish this?

EDIT: The code used for the transformation:

public String getPlaylist(String playlist) {
    Source source = new StreamSource(library);
    StreamSource xsl = new StreamSource(getClass().getResourceAsStream("M3Utransformation.xml"));
    StringWriter w = new StringWriter();
    Result result = new StreamResult(w);
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer(xsl);
        transformer.setParameter("playlist", playlist);
        transformer.transform(source, result);
        return w.getBuffer().toString();
    } catch (Throwable t) {
        t.printStackTrace();
        return null;
    }
}
3
  • According to W3C there is a lot of excessive DTD traffic, see w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic Which brings to mind the question, do you really need your dtd ? I'll pursue and answer to this question, but thought I'd ask first for you to provide the code sample which fails without access to the dtd Commented Jan 8, 2014 at 21:12
  • The XML file to transform isn't created by me. It's a iTunes library. I don't want to mess around with the library itself. Commented Jan 8, 2014 at 21:15
  • 2
    Most XML parsers, and at least some XSLT processors, have an API which lets you write and plug in code that can provide special interpretation of some or all of the URLs/URIs. That can be used to recognize the DTD request and return an input stream obtained from wherever you want -- ranging from a string in memory to a local file to a file cache, depending on just how much work you want to do. This is usually referred to as a "DTD Resolver" or "Entity Resolver", depending on which API you're using to run the stylesheet. Commented Jan 8, 2014 at 21:45

1 Answer 1

4

You can create an entity resolver, and make use of it.

The following example uses the JAXP DocumentBuilder, and a CatalogResolver

public static void main(String[] args) throws ParserConfigurationException,
        SAXException, IOException, TransformerConfigurationException, TransformerException {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    db.setEntityResolver(new CatalogResolver());

    File src = new File("src/article.xml");
    Document doc = db.parse(src);

    // Here, we execute the transformation
    // Use a Transformer for output
    File stylesheet = new File("src/aticle.xsl");
    TransformerFactory tFactory = TransformerFactory.newInstance();
    StreamSource stylesource = new StreamSource(stylesheet);
    Transformer transformer = tFactory.newTransformer(stylesource);

    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(System.out);
    transformer.transform(source, result);
}

create a catalog properties file, and place it on your classpath CatalogManager.properties has to be the name, see CatalogManager API documentation

define a catalog XML file, point your properties file, above to it. From http://www.xml.com/pub/a/2004/03/03/catalogs.html you can find a very simple catalog XML file :

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <public publicId="-//OYRM/foo" uri="src/bar.dtd"/>
</catalog>

With the above catalog.xml and CatalogManager.properties, you'll end up resolving references to the publicId "-//OYRM/foo" to the uri src/bar.dtd xml-commons contains the resolver :

http://xerces.apache.org/mirrors.cgi#binary

for a more complete treatment of the topic of Resolvers read Tom White's article from XML.com

The transformer application was cribbed from the Java trail for Extensible StyleSheet Language Transformations > Transforming Data with XSLT

Sign up to request clarification or add additional context in comments.

3 Comments

And how would I give the Document doc to the transformer?
Edit Got it myself: new DOMSource(doc). Thank you very much.
I edited the above to complete the transformation and send the data to System.out ... Glad you got it @the_Seppi, but I thought I'd finish editing for completion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.