[jdom-interest] [PATCH] Allow Xslt transformations on documents
that require an EntityResolver
Jason Hunter
jhunter at servlets.com
Mon Feb 12 11:37:01 PST 2007
Thanks, Dave. I checked it into CVS.
-jh-
Dave Byrne wrote:
> When transforming a Document using XSLTransformer that required an
> EntityResolver to be parsed, SAXOutputter.dtdEvents() throws an
> exception as it is unable to locate any dtds/entities.
>
> Attached is a patch that adds an additional constructor to JDOMSource
> with an EntityResolver which is passed to the internal DocumentReader
> allowing the SAXOutputter to properly resolve dtds.
>
> Patch is against cvs HEAD. Any comments are welcomed.
>
> Thanks
> Dave Byrne
>
>
> ### Eclipse Workspace Patch 1.0
> #P Jdom
> Index: src/java/org/jdom/transform/JDOMSource.java
> ===================================================================
> RCS file:
> /home/cvspublic/jdom/src/java/org/jdom/transform/JDOMSource.java,v
> retrieving revision 1.18
> diff -u -r1.18 JDOMSource.java
> --- src/java/org/jdom/transform/JDOMSource.java 31 Aug 2004 04:43:48
> -0000 1.18
> +++ src/java/org/jdom/transform/JDOMSource.java 6 Feb 2007 15:19:58
> -0000
> @@ -124,6 +124,15 @@
> * @see #getXMLReader
> */
> private XMLReader xmlReader = null;
> +
> + /**
> + * Optional entity resolver associated to the source of
> + * this document or <code>null</code> if no EntityResolver
> + * was supplied with this JDOMSource.
> + *
> + * @see #buildDocumentReader()
> + */
> + private EntityResolver resolver = null;
>
> /**
> * Creates a JDOM TrAX source wrapping a JDOM document.
> @@ -168,6 +177,24 @@
> }
>
> /**
> + * Creates a JDOM TrAX source wrapping a JDOM element with an
> + * associated EntityResolver to resolve external entities.
> + *
> + * @param source The JDOM Element to use as source for
> the
> + * transformations
> + *
> + * @param resolver Entity resolver to use for the source
> + * transformation
> + *
> + * @throws IllegalArgumentException if<code>source</code> is
> + *
> <code>null</code>
> + */
> + public JDOMSource(Document source, EntityResolver resolver) {
> + setDocument(source);
> + this.resolver = resolver;
> + }
> +
> +/**
> * Sets the source document used by this TrAX source.
> *
> * @param source the JDOM document to use as source for the
> @@ -280,7 +307,7 @@
> while (filter.getParent() instanceof XMLFilter) {
> filter = (XMLFilter)(filter.getParent());
> }
> - filter.setParent(new DocumentReader());
> + filter.setParent(buildDocumentReader());
>
> // Read XML data from filter chain.
> this.xmlReader = reader;
> @@ -302,10 +329,25 @@
> */
> public XMLReader getXMLReader() {
> if (this.xmlReader == null) {
> - this.xmlReader = new DocumentReader();
> + this.xmlReader = buildDocumentReader();
> }
> return this.xmlReader;
> }
> +
> + /**
> + * Build an XMLReader to be used for the source. This will
> + * create a new instance of DocumentReader with an
> + * EntityResolver instance if available.
> + *
> + * @return XMLReader reading the XML data from the source
> + * JDOM document with an optional EntityResolver
> + */
> + private XMLReader buildDocumentReader() {
> + DocumentReader reader = new DocumentReader();
> + if(resolver != null)
> + reader.setEntityResolver(resolver);
> + return reader;
> + }
>
>
> //======================================================================
> ===
> // JDOMInputSource nested class
> Index: src/java/org/jdom/transform/XSLTransformer.java
> ===================================================================
> RCS file:
> /home/cvspublic/jdom/src/java/org/jdom/transform/XSLTransformer.java,v
> retrieving revision 1.2
> diff -u -r1.2 XSLTransformer.java
> --- src/java/org/jdom/transform/XSLTransformer.java 6 Feb 2004
> 09:28:32 -0000 1.2
> +++ src/java/org/jdom/transform/XSLTransformer.java 6 Feb 2007
> 15:19:58 -0000
> @@ -61,6 +61,7 @@
> import javax.xml.transform.*;
> import javax.xml.transform.stream.StreamSource;
> import org.jdom.*;
> +import org.xml.sax.EntityResolver;
>
> /**
> * A convenience class to handle simple transformations. The JAXP TrAX
> classes @@ -219,7 +220,7 @@
> throw new XSLTransformException("Could not perform
> transformation", e);
> }
> }
> -
> +
> /**
> * Transforms the given document to an output document.
> *
> @@ -228,7 +229,19 @@
> * @throws XSLTransformException if there's a problem in the
> transformation
> */
> public Document transform(Document inputDoc) throws
> XSLTransformException {
> - JDOMSource source = new JDOMSource(inputDoc);
> + return transform(inputDoc, null);
> + }
> +
> + /**
> + * Transforms the given document to an output document.
> + *
> + * @param inputDoc input document
> + * @param resolver entity resolver for
> the input document
> + * @return transformed output document
> + * @throws XSLTransformException if there's a problem in the
> transformation
> + */
> + public Document transform(Document inputDoc, EntityResolver
> resolver) throws XSLTransformException {
> + JDOMSource source = new JDOMSource(inputDoc, resolver);
> JDOMResult result = new JDOMResult();
> try {
> templates.newTransformer().transform(source, result);
>
> //Sample test exposing problem
>
> package test.jdom;
>
> import org.jdom.Document;
> import org.jdom.input.SAXBuilder;
> import org.jdom.output.Format;
> import org.jdom.output.XMLOutputter;
> import org.jdom.transform.XSLTransformer;
>
>
> public class TestEntityResolve {
>
> public static void main(String[] args) throws Exception {
>
> FolderEntityResolver resolver = new
> FolderEntityResolver("dtd");
>
> SAXBuilder builder = new SAXBuilder();
> builder.setEntityResolver(resolver);
> Document doc = builder.build(args[0]);
>
> XSLTransformer transformer = new
> XSLTransformer(args[1]);
>
> // will fail with cvs version of jdom
> //Document outputDoc = transformer.transform(doc);
>
> //will succeed with patch
> Document outputDoc = transformer.transform(doc,
> resolver);
>
> XMLOutputter out = new
> XMLOutputter(Format.getPrettyFormat());
> out.output(outputDoc, System.out);
>
> }
>
> }
>
> // Sample entity resolver which resolves all entities to files in a
> folder package test.jdom;
>
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.IOException;
>
> import org.xml.sax.EntityResolver;
> import org.xml.sax.InputSource;
> import org.xml.sax.SAXException;
>
> public class FolderEntityResolver implements EntityResolver {
>
> private File folder;
>
> public FolderEntityResolver(String folderStr) {
> this.folder = new File(folderStr);
> }
>
> public InputSource resolveEntity(String publicId, String
> systemId)
> throws SAXException, IOException {
> File[] files = folder.listFiles();
>
> File srcFile = new File(systemId);
> for(int i = 0; i < files.length; i++) {
> if(files[i].getName().equals(srcFile.getName()))
> {
> return new InputSource(new
> FileInputStream(files[i]));
> }
> }
> return null;
> }
>
> }
>
>
> //sample xml
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE foo SYSTEM "foo.dtd">
> <foo>
> <bar>&entRef;</bar>
> </foo>
>
> //sample dtd
> <?xml version="1.0" encoding="UTF-8"?>
>
> <!ENTITY entRef "" > <!--UE248 angle with down zig-zag arrow
> -->
> <!ELEMENT foo (bar) >
> <!ELEMENT bar (#PCDATA)>
>
>
> _______________________________________________
> To control your jdom-interest membership:
> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>
More information about the jdom-interest
mailing list