2206 lines
71 KiB
Diff
2206 lines
71 KiB
Diff
From a8228522a99a02146106672a34c104adbda5c658 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Filip=20Jirs=C3=A1k?= <filip@jirsak.org>
|
|
Date: Sat, 11 Apr 2020 19:06:44 +0200
|
|
Subject: [PATCH] SAXReader uses system default XMLReader with its defaults.
|
|
New factory method SAXReader.createDefault() sets more secure defaults.
|
|
|
|
---
|
|
src/main/java/org/dom4j/DocumentHelper.java | 65 +-
|
|
src/main/java/org/dom4j/io/SAXHelper.java | 37 +-
|
|
src/main/java/org/dom4j/io/SAXReader.java | 1824 ++++++++++---------
|
|
3 files changed, 973 insertions(+), 953 deletions(-)
|
|
|
|
diff --git a/src/main/java/org/dom4j/DocumentHelper.java b/src/main/java/org/dom4j/DocumentHelper.java
|
|
index 6ceed9a3..865a51a1 100644
|
|
--- a/src/main/java/org/dom4j/DocumentHelper.java
|
|
+++ b/src/main/java/org/dom4j/DocumentHelper.java
|
|
@@ -107,12 +107,12 @@ public static QName createQName(String localName) {
|
|
* XPath <code>XPath</code> instance using the singleton {@link
|
|
* DocumentFactory}.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathExpression
|
|
* is the XPath expression to create
|
|
- *
|
|
+ *
|
|
* @return a new <code>XPath</code> instance
|
|
- *
|
|
+ *
|
|
* @throws InvalidXPathException
|
|
* if the XPath expression is invalid
|
|
*/
|
|
@@ -127,14 +127,14 @@ public static XPath createXPath(String xpathExpression)
|
|
* XPath <code>XPath</code> instance using the singleton {@link
|
|
* DocumentFactory}.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathExpression
|
|
* is the XPath expression to create
|
|
* @param context
|
|
* is the variable context to use when evaluating the XPath
|
|
- *
|
|
+ *
|
|
* @return a new <code>XPath</code> instance
|
|
- *
|
|
+ *
|
|
* @throws InvalidXPathException
|
|
* if the XPath expression is invalid
|
|
*/
|
|
@@ -150,10 +150,10 @@ public static XPath createXPath(String xpathExpression,
|
|
* filter expressions occur within XPath expressions such as
|
|
* <code>self::node()[ filterExpression ]</code>
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathFilterExpression
|
|
* is the XPath filter expression to create
|
|
- *
|
|
+ *
|
|
* @return a new <code>NodeFilter</code> instance
|
|
*/
|
|
public static NodeFilter createXPathFilter(String xpathFilterExpression) {
|
|
@@ -166,10 +166,10 @@ public static NodeFilter createXPathFilter(String xpathFilterExpression) {
|
|
* an XSLT style {@link Pattern}instance which can then be used in an XSLT
|
|
* processing model.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathPattern
|
|
* is the XPath pattern expression to create
|
|
- *
|
|
+ *
|
|
* @return a new <code>Pattern</code> instance
|
|
*/
|
|
public static Pattern createPattern(String xpathPattern) {
|
|
@@ -182,12 +182,12 @@ public static Pattern createPattern(String xpathPattern) {
|
|
* {@link List}of {@link Node}instances appending all the results together
|
|
* into a single list.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathFilterExpression
|
|
* is the XPath filter expression to evaluate
|
|
* @param nodes
|
|
* is the list of nodes on which to evalute the XPath
|
|
- *
|
|
+ *
|
|
* @return the results of all the XPath evaluations as a single list
|
|
*/
|
|
public static List<Node> selectNodes(String xpathFilterExpression, List<Node> nodes) {
|
|
@@ -202,12 +202,12 @@ public static Pattern createPattern(String xpathPattern) {
|
|
* {@link List}of {@link Node}instances appending all the results together
|
|
* into a single list.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param xpathFilterExpression
|
|
* is the XPath filter expression to evaluate
|
|
* @param node
|
|
* is the Node on which to evalute the XPath
|
|
- *
|
|
+ *
|
|
* @return the results of all the XPath evaluations as a single list
|
|
*/
|
|
public static List<Node> selectNodes(String xpathFilterExpression, Node node) {
|
|
@@ -221,7 +221,7 @@ public static Pattern createPattern(String xpathPattern) {
|
|
* <code>sort</code> sorts the given List of Nodes using an XPath
|
|
* expression as a {@link java.util.Comparator}.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param list
|
|
* is the list of Nodes to sort
|
|
* @param xpathExpression
|
|
@@ -238,7 +238,7 @@ public static void sort(List<Node> list, String xpathExpression) {
|
|
* expression as a {@link java.util.Comparator}and optionally removing
|
|
* duplicates.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @param list
|
|
* is the list of Nodes to sort
|
|
* @param expression
|
|
@@ -259,24 +259,17 @@ public static void sort(List<Node> list, String expression, boolean distinct) {
|
|
* </p>
|
|
*
|
|
* Loading external DTD and entities is disabled (if it is possible) for security reasons.
|
|
- *
|
|
+ *
|
|
* @param text
|
|
* the XML text to be parsed
|
|
- *
|
|
+ *
|
|
* @return a newly parsed Document
|
|
- *
|
|
+ *
|
|
* @throws DocumentException
|
|
* if the document could not be parsed
|
|
*/
|
|
public static Document parseText(String text) throws DocumentException {
|
|
- SAXReader reader = new SAXReader();
|
|
- try {
|
|
- reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
- reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
- reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
- } catch (SAXException e) {
|
|
- //Parse with external resources downloading allowed.
|
|
- }
|
|
+ SAXReader reader = SAXReader.createDefault();
|
|
|
|
String encoding = getEncoding(text);
|
|
|
|
@@ -330,14 +323,14 @@ private static String getEncoding(String text) {
|
|
* get the first child <a> element, which would be created if it did
|
|
* not exist, then the next child <b> and so on until finally a
|
|
* <c> element is returned.
|
|
- *
|
|
+ *
|
|
* @param source
|
|
* is the Element or Document to start navigating from
|
|
* @param path
|
|
* is a simple path expression, seperated by '/' which denotes
|
|
* the path from the source to the resulting element such as
|
|
* a/b/c
|
|
- *
|
|
+ *
|
|
* @return the first Element on the given path which either already existed
|
|
* on the path or were created by this method.
|
|
*/
|
|
@@ -386,24 +379,24 @@ public static Element makeElement(Branch source, String path) {
|
|
* Redistribution and use of this software and associated documentation
|
|
* ("Software"), with or without modification, are permitted provided that the
|
|
* following conditions are met:
|
|
- *
|
|
+ *
|
|
* 1. Redistributions of source code must retain copyright statements and
|
|
* notices. Redistributions must also contain a copy of this document.
|
|
- *
|
|
+ *
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
- *
|
|
+ *
|
|
* 3. The name "DOM4J" must not be used to endorse or promote products derived
|
|
* from this Software without prior written permission of MetaStuff, Ltd. For
|
|
* written permission, please contact dom4j-info@metastuff.com.
|
|
- *
|
|
+ *
|
|
* 4. Products derived from this Software may not be called "DOM4J" nor may
|
|
* "DOM4J" appear in their names without prior written permission of MetaStuff,
|
|
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
|
|
- *
|
|
+ *
|
|
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
|
|
- *
|
|
+ *
|
|
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -415,6 +408,6 @@ public static Element makeElement(Branch source, String path) {
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
+ *
|
|
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
|
|
*/
|
|
diff --git a/src/main/java/org/dom4j/io/SAXHelper.java b/src/main/java/org/dom4j/io/SAXHelper.java
|
|
index d204d084..e66905e9 100644
|
|
--- a/src/main/java/org/dom4j/io/SAXHelper.java
|
|
+++ b/src/main/java/org/dom4j/io/SAXHelper.java
|
|
@@ -13,12 +13,14 @@
|
|
import org.xml.sax.XMLReader;
|
|
import org.xml.sax.helpers.XMLReaderFactory;
|
|
|
|
+import javax.xml.parsers.SAXParserFactory;
|
|
+
|
|
/**
|
|
* <p>
|
|
* <code>SAXHelper</code> contains some helper methods for working with SAX
|
|
* and XMLReader objects.
|
|
* </p>
|
|
- *
|
|
+ *
|
|
* @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
|
|
* @version $Revision: 1.18 $
|
|
*/
|
|
@@ -61,12 +63,21 @@ public static boolean setParserFeature(XMLReader reader,
|
|
/**
|
|
* Creats a default XMLReader via the org.xml.sax.driver system property or
|
|
* JAXP if the system property is not set.
|
|
- *
|
|
+ *
|
|
+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
|
|
+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
|
|
+ *
|
|
+ * <pre>
|
|
+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ * </pre>
|
|
+ *
|
|
* @param validating
|
|
* DOCUMENT ME!
|
|
- *
|
|
+ *
|
|
* @return DOCUMENT ME!
|
|
- *
|
|
+ *
|
|
* @throws SAXException
|
|
* DOCUMENT ME!
|
|
*/
|
|
@@ -125,12 +136,12 @@ public static XMLReader createXMLReader(boolean validating)
|
|
* This method attempts to use JAXP to locate the SAX2 XMLReader
|
|
* implementation. This method uses reflection to avoid being dependent
|
|
* directly on the JAXP classes.
|
|
- *
|
|
+ *
|
|
* @param validating
|
|
* DOCUMENT ME!
|
|
* @param namespaceAware
|
|
* DOCUMENT ME!
|
|
- *
|
|
+ *
|
|
* @return DOCUMENT ME!
|
|
*/
|
|
protected static XMLReader createXMLReaderViaJAXP(boolean validating,
|
|
@@ -176,24 +187,24 @@ protected static boolean isVerboseErrorReporting() {
|
|
* Redistribution and use of this software and associated documentation
|
|
* ("Software"), with or without modification, are permitted provided that the
|
|
* following conditions are met:
|
|
- *
|
|
+ *
|
|
* 1. Redistributions of source code must retain copyright statements and
|
|
* notices. Redistributions must also contain a copy of this document.
|
|
- *
|
|
+ *
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
- *
|
|
+ *
|
|
* 3. The name "DOM4J" must not be used to endorse or promote products derived
|
|
* from this Software without prior written permission of MetaStuff, Ltd. For
|
|
* written permission, please contact dom4j-info@metastuff.com.
|
|
- *
|
|
+ *
|
|
* 4. Products derived from this Software may not be called "DOM4J" nor may
|
|
* "DOM4J" appear in their names without prior written permission of MetaStuff,
|
|
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
|
|
- *
|
|
+ *
|
|
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
|
|
- *
|
|
+ *
|
|
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -205,6 +216,6 @@ protected static boolean isVerboseErrorReporting() {
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
+ *
|
|
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
|
|
*/
|
|
diff --git a/src/main/java/org/dom4j/io/SAXReader.java b/src/main/java/org/dom4j/io/SAXReader.java
|
|
index 6bb3d926..73660abf 100644
|
|
--- a/src/main/java/org/dom4j/io/SAXReader.java
|
|
+++ b/src/main/java/org/dom4j/io/SAXReader.java
|
|
@@ -30,32 +30,34 @@
|
|
import org.xml.sax.helpers.DefaultHandler;
|
|
import org.xml.sax.helpers.XMLReaderFactory;
|
|
|
|
+import javax.xml.parsers.SAXParserFactory;
|
|
+
|
|
/**
|
|
* <code>SAXReader</code> creates a DOM4J tree from SAX parsing events.
|
|
- *
|
|
+ * <p>
|
|
* The actual SAX parser that is used by this class is configurable so you can
|
|
* use your favourite SAX parser if you wish. DOM4J comes configured with its
|
|
* own SAX parser so you do not need to worry about configuring the SAX parser.
|
|
- *
|
|
+ * <p>
|
|
* To explicitly configure the SAX parser that is used via Java code you can use
|
|
* a constructor or use the {@link #setXMLReader(XMLReader)}or {@link
|
|
* #setXMLReaderClassName(String)} methods.
|
|
- *
|
|
+ * <p>
|
|
* If the parser is not specified explicitly then the standard SAX policy of
|
|
* using the <code>org.xml.sax.driver</code> system property is used to
|
|
* determine the implementation class of {@link XMLReader}.
|
|
- *
|
|
+ * <p>
|
|
* If the <code>org.xml.sax.driver</code> system property is not defined then
|
|
* JAXP is used via reflection (so that DOM4J is not explicitly dependent on the
|
|
* JAXP classes) to load the JAXP configured SAXParser. If there is any error
|
|
* creating a JAXP SAXParser an informational message is output and then the
|
|
* default (Aelfred) SAX parser is used instead.
|
|
- *
|
|
+ * <p>
|
|
* If you are trying to use JAXP to explicitly set your SAX parser and are
|
|
* experiencing problems, you can turn on verbose error reporting by defining
|
|
* the system property <code>org.dom4j.verbose</code> to be "true" which will
|
|
* output a more detailed description of why JAXP could not find a SAX parser
|
|
- *
|
|
+ * <p>
|
|
* For more information on JAXP please go to <a
|
|
* href="http://java.sun.com/xml/">Sun's Java & XML site </a>
|
|
*
|
|
@@ -63,932 +65,946 @@
|
|
* @version $Revision: 1.58 $
|
|
*/
|
|
public class SAXReader {
|
|
- private static final String SAX_STRING_INTERNING =
|
|
- "http://xml.org/sax/features/string-interning";
|
|
- private static final String SAX_DECL_HANDLER =
|
|
- "http://xml.org/sax/properties/declaration-handler";
|
|
- private static final String SAX_LEXICAL_HANDLER =
|
|
- "http://xml.org/sax/properties/lexical-handler";
|
|
- private static final String SAX_LEXICALHANDLER =
|
|
- "http://xml.org/sax/handlers/LexicalHandler";
|
|
-
|
|
- /** <code>DocumentFactory</code> used to create new document objects */
|
|
- private DocumentFactory factory;
|
|
-
|
|
- /** <code>XMLReader</code> used to parse the SAX events */
|
|
- private XMLReader xmlReader;
|
|
-
|
|
- /** Whether validation should occur */
|
|
- private boolean validating;
|
|
-
|
|
- /** DispatchHandler to call when each <code>Element</code> is encountered */
|
|
- private DispatchHandler dispatchHandler;
|
|
-
|
|
- /** ErrorHandler class to use */
|
|
- private ErrorHandler errorHandler;
|
|
-
|
|
- /** The entity resolver */
|
|
- private EntityResolver entityResolver;
|
|
-
|
|
- /** Should element & attribute names and namespace URIs be interned? */
|
|
- private boolean stringInternEnabled = true;
|
|
-
|
|
- /** Should internal DTD declarations be expanded into a List in the DTD */
|
|
- private boolean includeInternalDTDDeclarations = false;
|
|
-
|
|
- /** Should external DTD declarations be expanded into a List in the DTD */
|
|
- private boolean includeExternalDTDDeclarations = false;
|
|
-
|
|
- /** Whether adjacent text nodes should be merged */
|
|
- private boolean mergeAdjacentText = false;
|
|
-
|
|
- /** Holds value of property stripWhitespaceText. */
|
|
- private boolean stripWhitespaceText = false;
|
|
-
|
|
- /** Should we ignore comments */
|
|
- private boolean ignoreComments = false;
|
|
-
|
|
- /** Encoding of InputSource - null means system default encoding */
|
|
- private String encoding = null;
|
|
-
|
|
- // private boolean includeExternalGeneralEntities = false;
|
|
- // private boolean includeExternalParameterEntities = false;
|
|
-
|
|
- /** The SAX filter used to filter SAX events */
|
|
- private XMLFilter xmlFilter;
|
|
-
|
|
- public SAXReader() {
|
|
- }
|
|
-
|
|
- public SAXReader(boolean validating) {
|
|
- this.validating = validating;
|
|
- }
|
|
-
|
|
- public SAXReader(DocumentFactory factory) {
|
|
- this.factory = factory;
|
|
- }
|
|
-
|
|
- public SAXReader(DocumentFactory factory, boolean validating) {
|
|
- this.factory = factory;
|
|
- this.validating = validating;
|
|
- }
|
|
-
|
|
- public SAXReader(XMLReader xmlReader) {
|
|
- this.xmlReader = xmlReader;
|
|
- }
|
|
-
|
|
- public SAXReader(XMLReader xmlReader, boolean validating) {
|
|
- this.xmlReader = xmlReader;
|
|
- this.validating = validating;
|
|
- }
|
|
-
|
|
- public SAXReader(String xmlReaderClassName) throws SAXException {
|
|
- if (xmlReaderClassName != null) {
|
|
- this.xmlReader = XMLReaderFactory
|
|
- .createXMLReader(xmlReaderClassName);
|
|
+ private static final String SAX_STRING_INTERNING =
|
|
+ "http://xml.org/sax/features/string-interning";
|
|
+ private static final String SAX_DECL_HANDLER =
|
|
+ "http://xml.org/sax/properties/declaration-handler";
|
|
+ private static final String SAX_LEXICAL_HANDLER =
|
|
+ "http://xml.org/sax/properties/lexical-handler";
|
|
+ private static final String SAX_LEXICALHANDLER =
|
|
+ "http://xml.org/sax/handlers/LexicalHandler";
|
|
+
|
|
+ /**
|
|
+ * <code>DocumentFactory</code> used to create new document objects
|
|
+ */
|
|
+ private DocumentFactory factory;
|
|
+
|
|
+ /**
|
|
+ * <code>XMLReader</code> used to parse the SAX events
|
|
+ */
|
|
+ private XMLReader xmlReader;
|
|
+
|
|
+ /**
|
|
+ * Whether validation should occur
|
|
+ */
|
|
+ private boolean validating;
|
|
+
|
|
+ /**
|
|
+ * DispatchHandler to call when each <code>Element</code> is encountered
|
|
+ */
|
|
+ private DispatchHandler dispatchHandler;
|
|
+
|
|
+ /**
|
|
+ * ErrorHandler class to use
|
|
+ */
|
|
+ private ErrorHandler errorHandler;
|
|
+
|
|
+ /**
|
|
+ * The entity resolver
|
|
+ */
|
|
+ private EntityResolver entityResolver;
|
|
+
|
|
+ /**
|
|
+ * Should element & attribute names and namespace URIs be interned?
|
|
+ */
|
|
+ private boolean stringInternEnabled = true;
|
|
+
|
|
+ /**
|
|
+ * Should internal DTD declarations be expanded into a List in the DTD
|
|
+ */
|
|
+ private boolean includeInternalDTDDeclarations = false;
|
|
+
|
|
+ /**
|
|
+ * Should external DTD declarations be expanded into a List in the DTD
|
|
+ */
|
|
+ private boolean includeExternalDTDDeclarations = false;
|
|
+
|
|
+ /**
|
|
+ * Whether adjacent text nodes should be merged
|
|
+ */
|
|
+ private boolean mergeAdjacentText = false;
|
|
+
|
|
+ /**
|
|
+ * Holds value of property stripWhitespaceText.
|
|
+ */
|
|
+ private boolean stripWhitespaceText = false;
|
|
+
|
|
+ /**
|
|
+ * Should we ignore comments
|
|
+ */
|
|
+ private boolean ignoreComments = false;
|
|
+
|
|
+ /**
|
|
+ * Encoding of InputSource - null means system default encoding
|
|
+ */
|
|
+ private String encoding = null;
|
|
+
|
|
+ // private boolean includeExternalGeneralEntities = false;
|
|
+ // private boolean includeExternalParameterEntities = false;
|
|
+
|
|
+ /**
|
|
+ * The SAX filter used to filter SAX events
|
|
+ *
|
|
+ * @since 2.1.2
|
|
+ */
|
|
+ private XMLFilter xmlFilter;
|
|
+
|
|
+ public static SAXReader createDefault() {
|
|
+ SAXReader reader = new SAXReader();
|
|
+ try {
|
|
+ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ } catch (SAXException e) {
|
|
+ // nothing to do, incompatible reader
|
|
+ }
|
|
+ return reader;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
|
|
+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
|
|
+ *
|
|
+ * <pre>
|
|
+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ * </pre>
|
|
+ */
|
|
+ public SAXReader() {
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
|
|
+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
|
|
+ *
|
|
+ * <pre>
|
|
+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ * </pre>
|
|
+ *
|
|
+ * @param validating
|
|
+ */
|
|
+ public SAXReader(boolean validating) {
|
|
+ this.validating = validating;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
|
|
+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
|
|
+ *
|
|
+ * <pre>
|
|
+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ * </pre>
|
|
+ *
|
|
+ * @param factory
|
|
+ */
|
|
+ public SAXReader(DocumentFactory factory) {
|
|
+ this.factory = factory;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
|
|
+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
|
|
+ *
|
|
+ * <pre>
|
|
+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
+ * </pre>
|
|
+ *
|
|
+ * @param factory
|
|
+ * @param validating
|
|
+ */
|
|
+ public SAXReader(DocumentFactory factory, boolean validating) {
|
|
+ this.factory = factory;
|
|
+ this.validating = validating;
|
|
+ }
|
|
+
|
|
+ public SAXReader(XMLReader xmlReader) {
|
|
+ this.xmlReader = xmlReader;
|
|
+ }
|
|
+
|
|
+ public SAXReader(XMLReader xmlReader, boolean validating) {
|
|
+ this.xmlReader = xmlReader;
|
|
+ this.validating = validating;
|
|
+ }
|
|
+
|
|
+ public SAXReader(String xmlReaderClassName) throws SAXException {
|
|
+ if (xmlReaderClassName != null) {
|
|
+ this.xmlReader = XMLReaderFactory
|
|
+ .createXMLReader(xmlReaderClassName);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public SAXReader(String xmlReaderClassName, boolean validating)
|
|
+ throws SAXException {
|
|
+ if (xmlReaderClassName != null) {
|
|
+ this.xmlReader = XMLReaderFactory
|
|
+ .createXMLReader(xmlReaderClassName);
|
|
+ }
|
|
+
|
|
+ this.validating = validating;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Allows a SAX property to be set on the underlying SAX parser. This can be
|
|
+ * useful to set parser-specific properties such as the location of schema
|
|
+ * or DTD resources. Though use this method with caution as it has the
|
|
+ * possibility of breaking the standard behaviour. An alternative to calling
|
|
+ * this method is to correctly configure an XMLReader object instance and
|
|
+ * call the {@link #setXMLReader(XMLReader)}method
|
|
+ *
|
|
+ * @param name is the SAX property name
|
|
+ * @param value is the value of the SAX property
|
|
+ * @throws SAXException if the XMLReader could not be created or the property could
|
|
+ * not be changed.
|
|
+ */
|
|
+ public void setProperty(String name, Object value) throws SAXException {
|
|
+ getXMLReader().setProperty(name, value);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets a SAX feature on the underlying SAX parser. This can be useful to
|
|
+ * set parser-specific features. Though use this method with caution as it
|
|
+ * has the possibility of breaking the standard behaviour. An alternative to
|
|
+ * calling this method is to correctly configure an XMLReader object
|
|
+ * instance and call the {@link #setXMLReader(XMLReader)}method
|
|
+ *
|
|
+ * @param name is the SAX feature name
|
|
+ * @param value is the value of the SAX feature
|
|
+ * @throws SAXException if the XMLReader could not be created or the feature could
|
|
+ * not be changed.
|
|
+ */
|
|
+ public void setFeature(String name, boolean value) throws SAXException {
|
|
+ getXMLReader().setFeature(name, value);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given <code>File</code>
|
|
+ * </p>
|
|
+ *
|
|
+ * @param file is the <code>File</code> to read from.
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(File file) throws DocumentException {
|
|
+ try {
|
|
+ /*
|
|
+ * We cannot convert the file to an URL because if the filename
|
|
+ * contains '#' characters, there will be problems with the URL in
|
|
+ * the InputSource (because a URL like
|
|
+ * http://myhost.com/index#anchor is treated the same as
|
|
+ * http://myhost.com/index) Thanks to Christian Oetterli
|
|
+ */
|
|
+ InputSource source = new InputSource(new FileInputStream(file));
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+ String path = file.getAbsolutePath();
|
|
+
|
|
+ if (path != null) {
|
|
+ // Code taken from Ant FileUtils
|
|
+ StringBuffer sb = new StringBuffer("file://");
|
|
+
|
|
+ // add an extra slash for filesystems with drive-specifiers
|
|
+ if (!path.startsWith(File.separator)) {
|
|
+ sb.append("/");
|
|
}
|
|
- }
|
|
|
|
- public SAXReader(String xmlReaderClassName, boolean validating)
|
|
- throws SAXException {
|
|
- if (xmlReaderClassName != null) {
|
|
- this.xmlReader = XMLReaderFactory
|
|
- .createXMLReader(xmlReaderClassName);
|
|
+ path = path.replace('\\', '/');
|
|
+ sb.append(path);
|
|
+
|
|
+ source.setSystemId(sb.toString());
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ } catch (FileNotFoundException e) {
|
|
+ throw new DocumentException(e.getMessage(), e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given <code>URL</code> using SAX
|
|
+ * </p>
|
|
+ *
|
|
+ * @param url <code>URL</code> to read from.
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(URL url) throws DocumentException {
|
|
+ String systemID = url.toExternalForm();
|
|
+
|
|
+ InputSource source = new InputSource(systemID);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given URL or filename using SAX.
|
|
+ * </p>
|
|
+ *
|
|
+ * <p>
|
|
+ * If the systemId contains a <code>':'</code> character then it is
|
|
+ * assumed to be a URL otherwise its assumed to be a file name. If you want
|
|
+ * finer grained control over this mechansim then please explicitly pass in
|
|
+ * either a {@link URL}or a {@link File}instance instead of a {@link
|
|
+ * String} to denote the source of the document.
|
|
+ * </p>
|
|
+ *
|
|
+ * @param systemId is a URL for a document or a file name.
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(String systemId) throws DocumentException {
|
|
+ InputSource source = new InputSource(systemId);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given stream using SAX
|
|
+ * </p>
|
|
+ *
|
|
+ * @param in <code>InputStream</code> to read from.
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(InputStream in) throws DocumentException {
|
|
+ InputSource source = new InputSource(in);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Reads a Document from the given <code>Reader</code> using SAX
|
|
+ *
|
|
+ * @param reader is the reader for the input
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(Reader reader) throws DocumentException {
|
|
+ InputSource source = new InputSource(reader);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given stream using SAX
|
|
+ * </p>
|
|
+ *
|
|
+ * @param in <code>InputStream</code> to read from.
|
|
+ * @param systemId is the URI for the input
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(InputStream in, String systemId)
|
|
+ throws DocumentException {
|
|
+ InputSource source = new InputSource(in);
|
|
+ source.setSystemId(systemId);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given <code>Reader</code> using SAX
|
|
+ * </p>
|
|
+ *
|
|
+ * @param reader is the reader for the input
|
|
+ * @param systemId is the URI for the input
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(Reader reader, String systemId)
|
|
+ throws DocumentException {
|
|
+ InputSource source = new InputSource(reader);
|
|
+ source.setSystemId(systemId);
|
|
+ if (this.encoding != null) {
|
|
+ source.setEncoding(this.encoding);
|
|
+ }
|
|
+
|
|
+ return read(source);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * Reads a Document from the given <code>InputSource</code> using SAX
|
|
+ * </p>
|
|
+ *
|
|
+ * @param in <code>InputSource</code> to read from.
|
|
+ * @return the newly created Document instance
|
|
+ * @throws DocumentException if an error occurs during parsing.
|
|
+ */
|
|
+ public Document read(InputSource in) throws DocumentException {
|
|
+ try {
|
|
+ XMLReader reader = getXMLReader();
|
|
+
|
|
+ reader = installXMLFilter(reader);
|
|
+
|
|
+ EntityResolver thatEntityResolver = this.entityResolver;
|
|
+
|
|
+ if (thatEntityResolver == null) {
|
|
+ thatEntityResolver = createDefaultEntityResolver(in
|
|
+ .getSystemId());
|
|
+ this.entityResolver = thatEntityResolver;
|
|
+ }
|
|
+
|
|
+ reader.setEntityResolver(thatEntityResolver);
|
|
+
|
|
+ SAXContentHandler contentHandler = createContentHandler(reader);
|
|
+ contentHandler.setEntityResolver(thatEntityResolver);
|
|
+ contentHandler.setInputSource(in);
|
|
+
|
|
+ boolean internal = isIncludeInternalDTDDeclarations();
|
|
+ boolean external = isIncludeExternalDTDDeclarations();
|
|
+
|
|
+ contentHandler.setIncludeInternalDTDDeclarations(internal);
|
|
+ contentHandler.setIncludeExternalDTDDeclarations(external);
|
|
+ contentHandler.setMergeAdjacentText(isMergeAdjacentText());
|
|
+ contentHandler.setStripWhitespaceText(isStripWhitespaceText());
|
|
+ contentHandler.setIgnoreComments(isIgnoreComments());
|
|
+ reader.setContentHandler(contentHandler);
|
|
+
|
|
+ configureReader(reader, contentHandler);
|
|
+
|
|
+ reader.parse(in);
|
|
+
|
|
+ return contentHandler.getDocument();
|
|
+ } catch (Exception e) {
|
|
+ if (e instanceof SAXParseException) {
|
|
+ // e.printStackTrace();
|
|
+ SAXParseException parseException = (SAXParseException) e;
|
|
+ String systemId = parseException.getSystemId();
|
|
+
|
|
+ if (systemId == null) {
|
|
+ systemId = "";
|
|
}
|
|
|
|
- this.validating = validating;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Allows a SAX property to be set on the underlying SAX parser. This can be
|
|
- * useful to set parser-specific properties such as the location of schema
|
|
- * or DTD resources. Though use this method with caution as it has the
|
|
- * possibility of breaking the standard behaviour. An alternative to calling
|
|
- * this method is to correctly configure an XMLReader object instance and
|
|
- * call the {@link #setXMLReader(XMLReader)}method
|
|
- *
|
|
- * @param name
|
|
- * is the SAX property name
|
|
- * @param value
|
|
- * is the value of the SAX property
|
|
- *
|
|
- * @throws SAXException
|
|
- * if the XMLReader could not be created or the property could
|
|
- * not be changed.
|
|
- */
|
|
- public void setProperty(String name, Object value) throws SAXException {
|
|
- getXMLReader().setProperty(name, value);
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets a SAX feature on the underlying SAX parser. This can be useful to
|
|
- * set parser-specific features. Though use this method with caution as it
|
|
- * has the possibility of breaking the standard behaviour. An alternative to
|
|
- * calling this method is to correctly configure an XMLReader object
|
|
- * instance and call the {@link #setXMLReader(XMLReader)}method
|
|
- *
|
|
- * @param name
|
|
- * is the SAX feature name
|
|
- * @param value
|
|
- * is the value of the SAX feature
|
|
- *
|
|
- * @throws SAXException
|
|
- * if the XMLReader could not be created or the feature could
|
|
- * not be changed.
|
|
- */
|
|
- public void setFeature(String name, boolean value) throws SAXException {
|
|
- getXMLReader().setFeature(name, value);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given <code>File</code>
|
|
- * </p>
|
|
- *
|
|
- * @param file
|
|
- * is the <code>File</code> to read from.
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(File file) throws DocumentException {
|
|
- try {
|
|
- /*
|
|
- * We cannot convert the file to an URL because if the filename
|
|
- * contains '#' characters, there will be problems with the URL in
|
|
- * the InputSource (because a URL like
|
|
- * http://myhost.com/index#anchor is treated the same as
|
|
- * http://myhost.com/index) Thanks to Christian Oetterli
|
|
- */
|
|
- InputSource source = new InputSource(new FileInputStream(file));
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
- String path = file.getAbsolutePath();
|
|
-
|
|
- if (path != null) {
|
|
- // Code taken from Ant FileUtils
|
|
- StringBuffer sb = new StringBuffer("file://");
|
|
-
|
|
- // add an extra slash for filesystems with drive-specifiers
|
|
- if (!path.startsWith(File.separator)) {
|
|
- sb.append("/");
|
|
- }
|
|
-
|
|
- path = path.replace('\\', '/');
|
|
- sb.append(path);
|
|
-
|
|
- source.setSystemId(sb.toString());
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- } catch (FileNotFoundException e) {
|
|
- throw new DocumentException(e.getMessage(), e);
|
|
+ String message = "Error on line "
|
|
+ + parseException.getLineNumber() + " of document "
|
|
+ + systemId + " : " + parseException.getMessage();
|
|
+
|
|
+ throw new DocumentException(message, e);
|
|
+ } else {
|
|
+ throw new DocumentException(e.getMessage(), e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Properties
|
|
+ // -------------------------------------------------------------------------
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return the validation mode, true if validating will be done otherwise
|
|
+ * false.
|
|
+ */
|
|
+ public boolean isValidating() {
|
|
+ return validating;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the validation mode.
|
|
+ *
|
|
+ * @param validation indicates whether or not validation should occur.
|
|
+ */
|
|
+ public void setValidation(boolean validation) {
|
|
+ this.validating = validation;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return whether internal DTD declarations should be expanded into the
|
|
+ * DocumentType object or not.
|
|
+ */
|
|
+ public boolean isIncludeInternalDTDDeclarations() {
|
|
+ return includeInternalDTDDeclarations;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether internal DTD declarations should be expanded into the
|
|
+ * DocumentType object or not.
|
|
+ *
|
|
+ * @param include whether or not DTD declarations should be expanded and
|
|
+ * included into the DocumentType object.
|
|
+ */
|
|
+ public void setIncludeInternalDTDDeclarations(boolean include) {
|
|
+ this.includeInternalDTDDeclarations = include;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return whether external DTD declarations should be expanded into the
|
|
+ * DocumentType object or not.
|
|
+ */
|
|
+ public boolean isIncludeExternalDTDDeclarations() {
|
|
+ return includeExternalDTDDeclarations;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether DTD external declarations should be expanded into the
|
|
+ * DocumentType object or not.
|
|
+ *
|
|
+ * @param include whether or not DTD declarations should be expanded and
|
|
+ * included into the DocumentType object.
|
|
+ */
|
|
+ public void setIncludeExternalDTDDeclarations(boolean include) {
|
|
+ this.includeExternalDTDDeclarations = include;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether String interning is enabled or disabled for element &
|
|
+ * attribute names and namespace URIs. This proprety is enabled by default.
|
|
+ *
|
|
+ * @return DOCUMENT ME!
|
|
+ */
|
|
+ public boolean isStringInternEnabled() {
|
|
+ return stringInternEnabled;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether String interning is enabled or disabled for element &
|
|
+ * attribute names and namespace URIs
|
|
+ *
|
|
+ * @param stringInternEnabled DOCUMENT ME!
|
|
+ */
|
|
+ public void setStringInternEnabled(boolean stringInternEnabled) {
|
|
+ this.stringInternEnabled = stringInternEnabled;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns whether adjacent text nodes should be merged together.
|
|
+ *
|
|
+ * @return Value of property mergeAdjacentText.
|
|
+ */
|
|
+ public boolean isMergeAdjacentText() {
|
|
+ return mergeAdjacentText;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether or not adjacent text nodes should be merged together when
|
|
+ * parsing.
|
|
+ *
|
|
+ * @param mergeAdjacentText New value of property mergeAdjacentText.
|
|
+ */
|
|
+ public void setMergeAdjacentText(boolean mergeAdjacentText) {
|
|
+ this.mergeAdjacentText = mergeAdjacentText;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether whitespace between element start and end tags should be
|
|
+ * ignored
|
|
+ *
|
|
+ * @return Value of property stripWhitespaceText.
|
|
+ */
|
|
+ public boolean isStripWhitespaceText() {
|
|
+ return stripWhitespaceText;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether whitespace between element start and end tags should be
|
|
+ * ignored.
|
|
+ *
|
|
+ * @param stripWhitespaceText New value of property stripWhitespaceText.
|
|
+ */
|
|
+ public void setStripWhitespaceText(boolean stripWhitespaceText) {
|
|
+ this.stripWhitespaceText = stripWhitespaceText;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns whether we should ignore comments or not.
|
|
+ *
|
|
+ * @return boolean
|
|
+ */
|
|
+ public boolean isIgnoreComments() {
|
|
+ return ignoreComments;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets whether we should ignore comments or not.
|
|
+ *
|
|
+ * @param ignoreComments whether we should ignore comments or not.
|
|
+ */
|
|
+ public void setIgnoreComments(boolean ignoreComments) {
|
|
+ this.ignoreComments = ignoreComments;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return the <code>DocumentFactory</code> used to create document
|
|
+ * objects
|
|
+ */
|
|
+ public DocumentFactory getDocumentFactory() {
|
|
+ if (factory == null) {
|
|
+ factory = DocumentFactory.getInstance();
|
|
+ }
|
|
+
|
|
+ return factory;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * <p>
|
|
+ * This sets the <code>DocumentFactory</code> used to create new
|
|
+ * documents. This method allows the building of custom DOM4J tree objects
|
|
+ * to be implemented easily using a custom derivation of
|
|
+ * {@link DocumentFactory}
|
|
+ * </p>
|
|
+ *
|
|
+ * @param documentFactory <code>DocumentFactory</code> used to create DOM4J objects
|
|
+ */
|
|
+ public void setDocumentFactory(DocumentFactory documentFactory) {
|
|
+ this.factory = documentFactory;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return the <code>ErrorHandler</code> used by SAX
|
|
+ */
|
|
+ public ErrorHandler getErrorHandler() {
|
|
+ return errorHandler;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the <code>ErrorHandler</code> used by the SAX
|
|
+ * <code>XMLReader</code>.
|
|
+ *
|
|
+ * @param errorHandler is the <code>ErrorHandler</code> used by SAX
|
|
+ */
|
|
+ public void setErrorHandler(ErrorHandler errorHandler) {
|
|
+ this.errorHandler = errorHandler;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the current entity resolver used to resolve entities
|
|
+ *
|
|
+ * @return DOCUMENT ME!
|
|
+ */
|
|
+ public EntityResolver getEntityResolver() {
|
|
+ return entityResolver;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the entity resolver used to resolve entities.
|
|
+ *
|
|
+ * @param entityResolver DOCUMENT ME!
|
|
+ */
|
|
+ public void setEntityResolver(EntityResolver entityResolver) {
|
|
+ this.entityResolver = entityResolver;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * DOCUMENT ME!
|
|
+ *
|
|
+ * @return the <code>XMLReader</code> used to parse SAX events
|
|
+ * @throws SAXException DOCUMENT ME!
|
|
+ */
|
|
+ public XMLReader getXMLReader() throws SAXException {
|
|
+ if (xmlReader == null) {
|
|
+ xmlReader = createXMLReader();
|
|
+ }
|
|
+
|
|
+ return xmlReader;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the <code>XMLReader</code> used to parse SAX events
|
|
+ *
|
|
+ * @param reader is the <code>XMLReader</code> to parse SAX events
|
|
+ */
|
|
+ public void setXMLReader(XMLReader reader) {
|
|
+ this.xmlReader = reader;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns encoding used for InputSource (null means system default
|
|
+ * encoding)
|
|
+ *
|
|
+ * @return encoding used for InputSource
|
|
+ */
|
|
+ public String getEncoding() {
|
|
+ return encoding;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets encoding used for InputSource (null means system default encoding)
|
|
+ *
|
|
+ * @param encoding is encoding used for InputSource
|
|
+ */
|
|
+ public void setEncoding(String encoding) {
|
|
+ this.encoding = encoding;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the class name of the <code>XMLReader</code> to be used to parse
|
|
+ * SAX events.
|
|
+ *
|
|
+ * @param xmlReaderClassName is the class name of the <code>XMLReader</code> to parse SAX
|
|
+ * events
|
|
+ * @throws SAXException DOCUMENT ME!
|
|
+ */
|
|
+ public void setXMLReaderClassName(String xmlReaderClassName)
|
|
+ throws SAXException {
|
|
+ setXMLReader(XMLReaderFactory.createXMLReader(xmlReaderClassName));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Adds the <code>ElementHandler</code> to be called when the specified
|
|
+ * path is encounted.
|
|
+ *
|
|
+ * @param path is the path to be handled
|
|
+ * @param handler is the <code>ElementHandler</code> to be called by the event
|
|
+ * based processor.
|
|
+ */
|
|
+ public void addHandler(String path, ElementHandler handler) {
|
|
+ getDispatchHandler().addHandler(path, handler);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Removes the <code>ElementHandler</code> from the event based processor,
|
|
+ * for the specified path.
|
|
+ *
|
|
+ * @param path is the path to remove the <code>ElementHandler</code> for.
|
|
+ */
|
|
+ public void removeHandler(String path) {
|
|
+ getDispatchHandler().removeHandler(path);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * When multiple <code>ElementHandler</code> instances have been
|
|
+ * registered, this will set a default <code>ElementHandler</code> to be
|
|
+ * called for any path which does <b>NOT </b> have a handler registered.
|
|
+ *
|
|
+ * @param handler is the <code>ElementHandler</code> to be called by the event
|
|
+ * based processor.
|
|
+ */
|
|
+ public void setDefaultHandler(ElementHandler handler) {
|
|
+ getDispatchHandler().setDefaultHandler(handler);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This method clears out all the existing handlers and default handler
|
|
+ * setting things back as if no handler existed. Useful when reusing an
|
|
+ * object instance.
|
|
+ */
|
|
+ public void resetHandlers() {
|
|
+ getDispatchHandler().resetHandlers();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the SAX filter being used to filter SAX events.
|
|
+ *
|
|
+ * @return the SAX filter being used or null if no SAX filter is installed
|
|
+ */
|
|
+ public XMLFilter getXMLFilter() {
|
|
+ return xmlFilter;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the SAX filter to be used when filtering SAX events
|
|
+ *
|
|
+ * @param filter is the SAX filter to use or null to disable filtering
|
|
+ */
|
|
+ public void setXMLFilter(XMLFilter filter) {
|
|
+ this.xmlFilter = filter;
|
|
+ }
|
|
+
|
|
+ // Implementation methods
|
|
+ // -------------------------------------------------------------------------
|
|
+
|
|
+ /**
|
|
+ * Installs any XMLFilter objects required to allow the SAX event stream to
|
|
+ * be filtered and preprocessed before it gets to dom4j.
|
|
+ *
|
|
+ * @param reader DOCUMENT ME!
|
|
+ * @return the new XMLFilter if applicable or the original XMLReader if no
|
|
+ * filter is being used.
|
|
+ */
|
|
+ protected XMLReader installXMLFilter(XMLReader reader) {
|
|
+ XMLFilter filter = getXMLFilter();
|
|
+
|
|
+ if (filter != null) {
|
|
+ // find the root XMLFilter
|
|
+ XMLFilter root = filter;
|
|
+
|
|
+ while (true) {
|
|
+ XMLReader parent = root.getParent();
|
|
+
|
|
+ if (parent instanceof XMLFilter) {
|
|
+ root = (XMLFilter) parent;
|
|
+ } else {
|
|
+ break;
|
|
}
|
|
+ }
|
|
+
|
|
+ root.setParent(reader);
|
|
+
|
|
+ return filter;
|
|
}
|
|
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given <code>URL</code> using SAX
|
|
- * </p>
|
|
- *
|
|
- * @param url
|
|
- * <code>URL</code> to read from.
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(URL url) throws DocumentException {
|
|
- String systemID = url.toExternalForm();
|
|
-
|
|
- InputSource source = new InputSource(systemID);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
+ return reader;
|
|
+ }
|
|
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given URL or filename using SAX.
|
|
- * </p>
|
|
- *
|
|
- * <p>
|
|
- * If the systemId contains a <code>':'</code> character then it is
|
|
- * assumed to be a URL otherwise its assumed to be a file name. If you want
|
|
- * finer grained control over this mechansim then please explicitly pass in
|
|
- * either a {@link URL}or a {@link File}instance instead of a {@link
|
|
- * String} to denote the source of the document.
|
|
- * </p>
|
|
- *
|
|
- * @param systemId
|
|
- * is a URL for a document or a file name.
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(String systemId) throws DocumentException {
|
|
- InputSource source = new InputSource(systemId);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given stream using SAX
|
|
- * </p>
|
|
- *
|
|
- * @param in
|
|
- * <code>InputStream</code> to read from.
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(InputStream in) throws DocumentException {
|
|
- InputSource source = new InputSource(in);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * Reads a Document from the given <code>Reader</code> using SAX
|
|
- *
|
|
- * @param reader
|
|
- * is the reader for the input
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(Reader reader) throws DocumentException {
|
|
- InputSource source = new InputSource(reader);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given stream using SAX
|
|
- * </p>
|
|
- *
|
|
- * @param in
|
|
- * <code>InputStream</code> to read from.
|
|
- * @param systemId
|
|
- * is the URI for the input
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(InputStream in, String systemId)
|
|
- throws DocumentException {
|
|
- InputSource source = new InputSource(in);
|
|
- source.setSystemId(systemId);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given <code>Reader</code> using SAX
|
|
- * </p>
|
|
- *
|
|
- * @param reader
|
|
- * is the reader for the input
|
|
- * @param systemId
|
|
- * is the URI for the input
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(Reader reader, String systemId)
|
|
- throws DocumentException {
|
|
- InputSource source = new InputSource(reader);
|
|
- source.setSystemId(systemId);
|
|
- if (this.encoding != null) {
|
|
- source.setEncoding(this.encoding);
|
|
- }
|
|
-
|
|
- return read(source);
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * Reads a Document from the given <code>InputSource</code> using SAX
|
|
- * </p>
|
|
- *
|
|
- * @param in
|
|
- * <code>InputSource</code> to read from.
|
|
- *
|
|
- * @return the newly created Document instance
|
|
- *
|
|
- * @throws DocumentException
|
|
- * if an error occurs during parsing.
|
|
- */
|
|
- public Document read(InputSource in) throws DocumentException {
|
|
- try {
|
|
- XMLReader reader = getXMLReader();
|
|
-
|
|
- reader = installXMLFilter(reader);
|
|
-
|
|
- EntityResolver thatEntityResolver = this.entityResolver;
|
|
-
|
|
- if (thatEntityResolver == null) {
|
|
- thatEntityResolver = createDefaultEntityResolver(in
|
|
- .getSystemId());
|
|
- this.entityResolver = thatEntityResolver;
|
|
- }
|
|
-
|
|
- reader.setEntityResolver(thatEntityResolver);
|
|
-
|
|
- SAXContentHandler contentHandler = createContentHandler(reader);
|
|
- contentHandler.setEntityResolver(thatEntityResolver);
|
|
- contentHandler.setInputSource(in);
|
|
-
|
|
- boolean internal = isIncludeInternalDTDDeclarations();
|
|
- boolean external = isIncludeExternalDTDDeclarations();
|
|
-
|
|
- contentHandler.setIncludeInternalDTDDeclarations(internal);
|
|
- contentHandler.setIncludeExternalDTDDeclarations(external);
|
|
- contentHandler.setMergeAdjacentText(isMergeAdjacentText());
|
|
- contentHandler.setStripWhitespaceText(isStripWhitespaceText());
|
|
- contentHandler.setIgnoreComments(isIgnoreComments());
|
|
- reader.setContentHandler(contentHandler);
|
|
-
|
|
- configureReader(reader, contentHandler);
|
|
-
|
|
- reader.parse(in);
|
|
-
|
|
- return contentHandler.getDocument();
|
|
- } catch (Exception e) {
|
|
- if (e instanceof SAXParseException) {
|
|
- // e.printStackTrace();
|
|
- SAXParseException parseException = (SAXParseException) e;
|
|
- String systemId = parseException.getSystemId();
|
|
-
|
|
- if (systemId == null) {
|
|
- systemId = "";
|
|
- }
|
|
-
|
|
- String message = "Error on line "
|
|
- + parseException.getLineNumber() + " of document "
|
|
- + systemId + " : " + parseException.getMessage();
|
|
-
|
|
- throw new DocumentException(message, e);
|
|
- } else {
|
|
- throw new DocumentException(e.getMessage(), e);
|
|
- }
|
|
+ protected DispatchHandler getDispatchHandler() {
|
|
+ if (dispatchHandler == null) {
|
|
+ dispatchHandler = new DispatchHandler();
|
|
+ }
|
|
+
|
|
+ return dispatchHandler;
|
|
+ }
|
|
+
|
|
+ protected void setDispatchHandler(DispatchHandler dispatchHandler) {
|
|
+ this.dispatchHandler = dispatchHandler;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Factory Method to allow alternate methods of creating and configuring
|
|
+ * XMLReader objects
|
|
+ *
|
|
+ * @return DOCUMENT ME!
|
|
+ * @throws SAXException DOCUMENT ME!
|
|
+ */
|
|
+ protected XMLReader createXMLReader() throws SAXException {
|
|
+ return SAXHelper.createXMLReader(isValidating());
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Configures the XMLReader before use
|
|
+ *
|
|
+ * @param reader DOCUMENT ME!
|
|
+ * @param handler DOCUMENT ME!
|
|
+ * @throws DocumentException DOCUMENT ME!
|
|
+ */
|
|
+ protected void configureReader(XMLReader reader, DefaultHandler handler)
|
|
+ throws DocumentException {
|
|
+ // configure lexical handling
|
|
+ SAXHelper.setParserProperty(reader, SAX_LEXICALHANDLER, handler);
|
|
+
|
|
+ // try alternate property just in case
|
|
+ SAXHelper.setParserProperty(reader, SAX_LEXICAL_HANDLER, handler);
|
|
+
|
|
+ // register the DeclHandler
|
|
+ if (includeInternalDTDDeclarations || includeExternalDTDDeclarations) {
|
|
+ SAXHelper.setParserProperty(reader, SAX_DECL_HANDLER, handler);
|
|
+ }
|
|
+
|
|
+ // string interning
|
|
+ SAXHelper.setParserFeature(reader, SAX_STRING_INTERNING,
|
|
+ isStringInternEnabled());
|
|
+
|
|
+ try {
|
|
+ // configure validation support
|
|
+ reader.setFeature("http://xml.org/sax/features/validation",
|
|
+ isValidating());
|
|
+
|
|
+ if (errorHandler != null) {
|
|
+ reader.setErrorHandler(errorHandler);
|
|
+ } else {
|
|
+ reader.setErrorHandler(handler);
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ if (isValidating()) {
|
|
+ throw new DocumentException("Validation not supported for"
|
|
+ + " XMLReader: " + reader, e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Factory Method to allow user derived SAXContentHandler objects to be used
|
|
+ *
|
|
+ * @param reader DOCUMENT ME!
|
|
+ * @return DOCUMENT ME!
|
|
+ */
|
|
+ protected SAXContentHandler createContentHandler(XMLReader reader) {
|
|
+ return new SAXContentHandler(getDocumentFactory(), dispatchHandler);
|
|
+ }
|
|
+
|
|
+ protected EntityResolver createDefaultEntityResolver(String systemId) {
|
|
+ String prefix = null;
|
|
+
|
|
+ if ((systemId != null) && (systemId.length() > 0)) {
|
|
+ int idx = systemId.lastIndexOf('/');
|
|
+
|
|
+ if (idx > 0) {
|
|
+ prefix = systemId.substring(0, idx + 1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return new SAXEntityResolver(prefix);
|
|
+ }
|
|
+
|
|
+ protected static class SAXEntityResolver implements EntityResolver,
|
|
+ Serializable {
|
|
+ protected String uriPrefix;
|
|
+
|
|
+ public SAXEntityResolver(String uriPrefix) {
|
|
+ this.uriPrefix = uriPrefix;
|
|
+ }
|
|
+
|
|
+ public InputSource resolveEntity(String publicId, String systemId) {
|
|
+ // try create a relative URI reader...
|
|
+ if ((systemId != null) && (systemId.length() > 0)) {
|
|
+ if ((uriPrefix != null) && (systemId.indexOf(':') <= 0)) {
|
|
+ systemId = uriPrefix + systemId;
|
|
}
|
|
- }
|
|
-
|
|
- // Properties
|
|
- // -------------------------------------------------------------------------
|
|
-
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return the validation mode, true if validating will be done otherwise
|
|
- * false.
|
|
- */
|
|
- public boolean isValidating() {
|
|
- return validating;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the validation mode.
|
|
- *
|
|
- * @param validation
|
|
- * indicates whether or not validation should occur.
|
|
- */
|
|
- public void setValidation(boolean validation) {
|
|
- this.validating = validation;
|
|
- }
|
|
+ }
|
|
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return whether internal DTD declarations should be expanded into the
|
|
- * DocumentType object or not.
|
|
- */
|
|
- public boolean isIncludeInternalDTDDeclarations() {
|
|
- return includeInternalDTDDeclarations;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether internal DTD declarations should be expanded into the
|
|
- * DocumentType object or not.
|
|
- *
|
|
- * @param include
|
|
- * whether or not DTD declarations should be expanded and
|
|
- * included into the DocumentType object.
|
|
- */
|
|
- public void setIncludeInternalDTDDeclarations(boolean include) {
|
|
- this.includeInternalDTDDeclarations = include;
|
|
- }
|
|
-
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return whether external DTD declarations should be expanded into the
|
|
- * DocumentType object or not.
|
|
- */
|
|
- public boolean isIncludeExternalDTDDeclarations() {
|
|
- return includeExternalDTDDeclarations;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether DTD external declarations should be expanded into the
|
|
- * DocumentType object or not.
|
|
- *
|
|
- * @param include
|
|
- * whether or not DTD declarations should be expanded and
|
|
- * included into the DocumentType object.
|
|
- */
|
|
- public void setIncludeExternalDTDDeclarations(boolean include) {
|
|
- this.includeExternalDTDDeclarations = include;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether String interning is enabled or disabled for element &
|
|
- * attribute names and namespace URIs. This proprety is enabled by default.
|
|
- *
|
|
- * @return DOCUMENT ME!
|
|
- */
|
|
- public boolean isStringInternEnabled() {
|
|
- return stringInternEnabled;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether String interning is enabled or disabled for element &
|
|
- * attribute names and namespace URIs
|
|
- *
|
|
- * @param stringInternEnabled
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- public void setStringInternEnabled(boolean stringInternEnabled) {
|
|
- this.stringInternEnabled = stringInternEnabled;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Returns whether adjacent text nodes should be merged together.
|
|
- *
|
|
- * @return Value of property mergeAdjacentText.
|
|
- */
|
|
- public boolean isMergeAdjacentText() {
|
|
- return mergeAdjacentText;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether or not adjacent text nodes should be merged together when
|
|
- * parsing.
|
|
- *
|
|
- * @param mergeAdjacentText
|
|
- * New value of property mergeAdjacentText.
|
|
- */
|
|
- public void setMergeAdjacentText(boolean mergeAdjacentText) {
|
|
- this.mergeAdjacentText = mergeAdjacentText;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether whitespace between element start and end tags should be
|
|
- * ignored
|
|
- *
|
|
- * @return Value of property stripWhitespaceText.
|
|
- */
|
|
- public boolean isStripWhitespaceText() {
|
|
- return stripWhitespaceText;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether whitespace between element start and end tags should be
|
|
- * ignored.
|
|
- *
|
|
- * @param stripWhitespaceText
|
|
- * New value of property stripWhitespaceText.
|
|
- */
|
|
- public void setStripWhitespaceText(boolean stripWhitespaceText) {
|
|
- this.stripWhitespaceText = stripWhitespaceText;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Returns whether we should ignore comments or not.
|
|
- *
|
|
- * @return boolean
|
|
- */
|
|
- public boolean isIgnoreComments() {
|
|
- return ignoreComments;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets whether we should ignore comments or not.
|
|
- *
|
|
- * @param ignoreComments
|
|
- * whether we should ignore comments or not.
|
|
- */
|
|
- public void setIgnoreComments(boolean ignoreComments) {
|
|
- this.ignoreComments = ignoreComments;
|
|
- }
|
|
-
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return the <code>DocumentFactory</code> used to create document
|
|
- * objects
|
|
- */
|
|
- public DocumentFactory getDocumentFactory() {
|
|
- if (factory == null) {
|
|
- factory = DocumentFactory.getInstance();
|
|
- }
|
|
-
|
|
- return factory;
|
|
- }
|
|
-
|
|
- /**
|
|
- * <p>
|
|
- * This sets the <code>DocumentFactory</code> used to create new
|
|
- * documents. This method allows the building of custom DOM4J tree objects
|
|
- * to be implemented easily using a custom derivation of
|
|
- * {@link DocumentFactory}
|
|
- * </p>
|
|
- *
|
|
- * @param documentFactory
|
|
- * <code>DocumentFactory</code> used to create DOM4J objects
|
|
- */
|
|
- public void setDocumentFactory(DocumentFactory documentFactory) {
|
|
- this.factory = documentFactory;
|
|
- }
|
|
-
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return the <code>ErrorHandler</code> used by SAX
|
|
- */
|
|
- public ErrorHandler getErrorHandler() {
|
|
- return errorHandler;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the <code>ErrorHandler</code> used by the SAX
|
|
- * <code>XMLReader</code>.
|
|
- *
|
|
- * @param errorHandler
|
|
- * is the <code>ErrorHandler</code> used by SAX
|
|
- */
|
|
- public void setErrorHandler(ErrorHandler errorHandler) {
|
|
- this.errorHandler = errorHandler;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Returns the current entity resolver used to resolve entities
|
|
- *
|
|
- * @return DOCUMENT ME!
|
|
- */
|
|
- public EntityResolver getEntityResolver() {
|
|
- return entityResolver;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the entity resolver used to resolve entities.
|
|
- *
|
|
- * @param entityResolver
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- public void setEntityResolver(EntityResolver entityResolver) {
|
|
- this.entityResolver = entityResolver;
|
|
- }
|
|
-
|
|
- /**
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return the <code>XMLReader</code> used to parse SAX events
|
|
- *
|
|
- * @throws SAXException
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- public XMLReader getXMLReader() throws SAXException {
|
|
- if (xmlReader == null) {
|
|
- xmlReader = createXMLReader();
|
|
- }
|
|
-
|
|
- return xmlReader;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the <code>XMLReader</code> used to parse SAX events
|
|
- *
|
|
- * @param reader
|
|
- * is the <code>XMLReader</code> to parse SAX events
|
|
- */
|
|
- public void setXMLReader(XMLReader reader) {
|
|
- this.xmlReader = reader;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Returns encoding used for InputSource (null means system default
|
|
- * encoding)
|
|
- *
|
|
- * @return encoding used for InputSource
|
|
- *
|
|
- */
|
|
- public String getEncoding() {
|
|
- return encoding;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets encoding used for InputSource (null means system default encoding)
|
|
- *
|
|
- * @param encoding
|
|
- * is encoding used for InputSource
|
|
- */
|
|
- public void setEncoding(String encoding) {
|
|
- this.encoding = encoding;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the class name of the <code>XMLReader</code> to be used to parse
|
|
- * SAX events.
|
|
- *
|
|
- * @param xmlReaderClassName
|
|
- * is the class name of the <code>XMLReader</code> to parse SAX
|
|
- * events
|
|
- *
|
|
- * @throws SAXException
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- public void setXMLReaderClassName(String xmlReaderClassName)
|
|
- throws SAXException {
|
|
- setXMLReader(XMLReaderFactory.createXMLReader(xmlReaderClassName));
|
|
- }
|
|
-
|
|
- /**
|
|
- * Adds the <code>ElementHandler</code> to be called when the specified
|
|
- * path is encounted.
|
|
- *
|
|
- * @param path
|
|
- * is the path to be handled
|
|
- * @param handler
|
|
- * is the <code>ElementHandler</code> to be called by the event
|
|
- * based processor.
|
|
- */
|
|
- public void addHandler(String path, ElementHandler handler) {
|
|
- getDispatchHandler().addHandler(path, handler);
|
|
- }
|
|
-
|
|
- /**
|
|
- * Removes the <code>ElementHandler</code> from the event based processor,
|
|
- * for the specified path.
|
|
- *
|
|
- * @param path
|
|
- * is the path to remove the <code>ElementHandler</code> for.
|
|
- */
|
|
- public void removeHandler(String path) {
|
|
- getDispatchHandler().removeHandler(path);
|
|
- }
|
|
-
|
|
- /**
|
|
- * When multiple <code>ElementHandler</code> instances have been
|
|
- * registered, this will set a default <code>ElementHandler</code> to be
|
|
- * called for any path which does <b>NOT </b> have a handler registered.
|
|
- *
|
|
- * @param handler
|
|
- * is the <code>ElementHandler</code> to be called by the event
|
|
- * based processor.
|
|
- */
|
|
- public void setDefaultHandler(ElementHandler handler) {
|
|
- getDispatchHandler().setDefaultHandler(handler);
|
|
- }
|
|
-
|
|
- /**
|
|
- * This method clears out all the existing handlers and default handler
|
|
- * setting things back as if no handler existed. Useful when reusing an
|
|
- * object instance.
|
|
- */
|
|
- public void resetHandlers() {
|
|
- getDispatchHandler().resetHandlers();
|
|
- }
|
|
-
|
|
- /**
|
|
- * Returns the SAX filter being used to filter SAX events.
|
|
- *
|
|
- * @return the SAX filter being used or null if no SAX filter is installed
|
|
- */
|
|
- public XMLFilter getXMLFilter() {
|
|
- return xmlFilter;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Sets the SAX filter to be used when filtering SAX events
|
|
- *
|
|
- * @param filter
|
|
- * is the SAX filter to use or null to disable filtering
|
|
- */
|
|
- public void setXMLFilter(XMLFilter filter) {
|
|
- this.xmlFilter = filter;
|
|
- }
|
|
-
|
|
- // Implementation methods
|
|
- // -------------------------------------------------------------------------
|
|
-
|
|
- /**
|
|
- * Installs any XMLFilter objects required to allow the SAX event stream to
|
|
- * be filtered and preprocessed before it gets to dom4j.
|
|
- *
|
|
- * @param reader
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return the new XMLFilter if applicable or the original XMLReader if no
|
|
- * filter is being used.
|
|
- */
|
|
- protected XMLReader installXMLFilter(XMLReader reader) {
|
|
- XMLFilter filter = getXMLFilter();
|
|
-
|
|
- if (filter != null) {
|
|
- // find the root XMLFilter
|
|
- XMLFilter root = filter;
|
|
-
|
|
- while (true) {
|
|
- XMLReader parent = root.getParent();
|
|
-
|
|
- if (parent instanceof XMLFilter) {
|
|
- root = (XMLFilter) parent;
|
|
- } else {
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- root.setParent(reader);
|
|
-
|
|
- return filter;
|
|
- }
|
|
-
|
|
- return reader;
|
|
- }
|
|
-
|
|
- protected DispatchHandler getDispatchHandler() {
|
|
- if (dispatchHandler == null) {
|
|
- dispatchHandler = new DispatchHandler();
|
|
- }
|
|
-
|
|
- return dispatchHandler;
|
|
- }
|
|
-
|
|
- protected void setDispatchHandler(DispatchHandler dispatchHandler) {
|
|
- this.dispatchHandler = dispatchHandler;
|
|
- }
|
|
-
|
|
- /**
|
|
- * Factory Method to allow alternate methods of creating and configuring
|
|
- * XMLReader objects
|
|
- *
|
|
- * @return DOCUMENT ME!
|
|
- *
|
|
- * @throws SAXException
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- protected XMLReader createXMLReader() throws SAXException {
|
|
- return SAXHelper.createXMLReader(isValidating());
|
|
- }
|
|
-
|
|
- /**
|
|
- * Configures the XMLReader before use
|
|
- *
|
|
- * @param reader
|
|
- * DOCUMENT ME!
|
|
- * @param handler
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @throws DocumentException
|
|
- * DOCUMENT ME!
|
|
- */
|
|
- protected void configureReader(XMLReader reader, DefaultHandler handler)
|
|
- throws DocumentException {
|
|
- // configure lexical handling
|
|
- SAXHelper.setParserProperty(reader, SAX_LEXICALHANDLER, handler);
|
|
-
|
|
- // try alternate property just in case
|
|
- SAXHelper.setParserProperty(reader, SAX_LEXICAL_HANDLER, handler);
|
|
-
|
|
- // register the DeclHandler
|
|
- if (includeInternalDTDDeclarations || includeExternalDTDDeclarations) {
|
|
- SAXHelper.setParserProperty(reader, SAX_DECL_HANDLER, handler);
|
|
- }
|
|
-
|
|
- // string interning
|
|
- SAXHelper.setParserFeature(reader, SAX_STRING_INTERNING,
|
|
- isStringInternEnabled());
|
|
-
|
|
- try {
|
|
- // configure validation support
|
|
- reader.setFeature("http://xml.org/sax/features/validation",
|
|
- isValidating());
|
|
-
|
|
- if (errorHandler != null) {
|
|
- reader.setErrorHandler(errorHandler);
|
|
- } else {
|
|
- reader.setErrorHandler(handler);
|
|
- }
|
|
- } catch (Exception e) {
|
|
- if (isValidating()) {
|
|
- throw new DocumentException("Validation not supported for"
|
|
- + " XMLReader: " + reader, e);
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /**
|
|
- * Factory Method to allow user derived SAXContentHandler objects to be used
|
|
- *
|
|
- * @param reader
|
|
- * DOCUMENT ME!
|
|
- *
|
|
- * @return DOCUMENT ME!
|
|
- */
|
|
- protected SAXContentHandler createContentHandler(XMLReader reader) {
|
|
- return new SAXContentHandler(getDocumentFactory(), dispatchHandler);
|
|
- }
|
|
-
|
|
- protected EntityResolver createDefaultEntityResolver(String systemId) {
|
|
- String prefix = null;
|
|
-
|
|
- if ((systemId != null) && (systemId.length() > 0)) {
|
|
- int idx = systemId.lastIndexOf('/');
|
|
-
|
|
- if (idx > 0) {
|
|
- prefix = systemId.substring(0, idx + 1);
|
|
- }
|
|
- }
|
|
-
|
|
- return new SAXEntityResolver(prefix);
|
|
- }
|
|
-
|
|
- protected static class SAXEntityResolver implements EntityResolver,
|
|
- Serializable {
|
|
- protected String uriPrefix;
|
|
-
|
|
- public SAXEntityResolver(String uriPrefix) {
|
|
- this.uriPrefix = uriPrefix;
|
|
- }
|
|
-
|
|
- public InputSource resolveEntity(String publicId, String systemId) {
|
|
- // try create a relative URI reader...
|
|
- if ((systemId != null) && (systemId.length() > 0)) {
|
|
- if ((uriPrefix != null) && (systemId.indexOf(':') <= 0)) {
|
|
- systemId = uriPrefix + systemId;
|
|
- }
|
|
- }
|
|
-
|
|
- return new InputSource(systemId);
|
|
- }
|
|
+ return new InputSource(systemId);
|
|
}
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
* Redistribution and use of this software and associated documentation
|
|
* ("Software"), with or without modification, are permitted provided that the
|
|
* following conditions are met:
|
|
- *
|
|
+ *
|
|
* 1. Redistributions of source code must retain copyright statements and
|
|
* notices. Redistributions must also contain a copy of this document.
|
|
- *
|
|
+ *
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
- *
|
|
+ *
|
|
* 3. The name "DOM4J" must not be used to endorse or promote products derived
|
|
* from this Software without prior written permission of MetaStuff, Ltd. For
|
|
* written permission, please contact dom4j-info@metastuff.com.
|
|
- *
|
|
+ *
|
|
* 4. Products derived from this Software may not be called "DOM4J" nor may
|
|
* "DOM4J" appear in their names without prior written permission of MetaStuff,
|
|
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
|
|
- *
|
|
+ *
|
|
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
|
|
- *
|
|
+ *
|
|
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -1000,6 +1016,6 @@ public InputSource resolveEntity(String publicId, String systemId) {
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
+ *
|
|
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
|
|
*/
|