[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    "&#57928;" > <!--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