[jdom-interest] [PATCH] Allow Xslt transformations on documents
that require an EntityResolver
Dave Byrne
dbyrne at mdb.com
Tue Feb 6 07:38:30 PST 2007
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)>
More information about the jdom-interest
mailing list