* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- */
+ */
package org.wamblee.xml;
import java.util.Map;
import java.util.TreeMap;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.dom4j.DocumentException;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
+import com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl;
+
/**
- * Some basic XML utilities for common reoccuring tasks for
- * DOM documents.
+ * Some basic XML utilities for common reoccuring tasks for DOM documents.
*/
public final class DomUtils {
-
+
+ private static final Log LOG = LogFactory.getLog(DomUtils.class);
+
/**
- * Disabled default constructor.
- *
+ * Disabled default constructor.
+ *
*/
- private DomUtils() {
- // Empty.
+ private DomUtils() {
+ // Empty.
}
-
+
/**
- * Parses an XML document from a string.
- * @param aDocument document.
- * @return
+ * Parses an XML document from a string.
+ *
+ * @param aDocument
+ * document.
+ * @return
*/
- public static Document read(String aDocument) throws SAXException, ParserConfigurationException, IOException {
+ public static Document read(String aDocument) throws XMLException {
ByteArrayInputStream is = new ByteArrayInputStream(aDocument.getBytes());
- return read(is);
+ return read(is);
}
-
+
/**
- * Parses an XML document from a stream.
- * @param aIs Input stream.
+ * Parses an XML document from a stream.
+ *
+ * @param aIs
+ * Input stream.
* @return
*/
- public static Document read(InputStream aIs) throws SAXException, ParserConfigurationException, IOException {
- DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- return builder.parse(aIs);
+ public static Document read(InputStream aIs) throws XMLException {
+ try {
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+ return builder.parse(aIs);
+ } catch (SAXException e) {
+ throw new XMLException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new XMLException(e.getMessage(), e);
+ } catch (ParserConfigurationException e) {
+ throw new XMLException(e.getMessage(), e);
+ } finally {
+ try {
+ aIs.close();
+ } catch (Exception e) {
+ LOG.warn("Error closing XML file", e);
+ }
+ }
}
/**
- * Serializes an XML document to a stream.
- * @param aDocument Document to serialize.
- * @param aOs Output stream.
+ * Reads and validates a document against a schema.
+ *
+ * @param aIs
+ * Input stream.
+ * @param aSchema
+ * Schema.
+ * @return Parsed and validated document.
*/
- public static void serialize(Document aDocument, OutputStream aOs) throws IOException {
+ public static Document readAndValidate(InputStream aIs, InputStream aSchema)
+ throws XMLException {
+
+ try {
+ final Schema schema = SchemaFactory.newInstance(
+ XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(
+ new StreamSource(aSchema));
+
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setValidating(true);
+ factory.setNamespaceAware(true);
+ factory.setSchema(schema);
+
+ return factory.newDocumentBuilder().parse(aIs);
+ } catch (SAXException e) {
+ throw new XMLException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new XMLException(e.getMessage(), e);
+ } catch (ParserConfigurationException e) {
+ throw new XMLException(e.getMessage(), e);
+ } finally {
+ try {
+ aSchema.close();
+ } catch (Exception e) {
+ LOG.warn("Error closing schema", e);
+ }
+ try {
+ aIs.close();
+ } catch (Exception e) {
+ LOG.warn("Error closing XML file", e);
+ }
+ }
+
+ }
+
+ /**
+ * Serializes an XML document to a stream.
+ *
+ * @param aDocument
+ * Document to serialize.
+ * @param aOs
+ * Output stream.
+ */
+ public static void serialize(Document aDocument, OutputStream aOs)
+ throws IOException {
XMLSerializer serializer = new XMLSerializer(aOs, new OutputFormat());
serializer.serialize(aDocument);
}
-
+
/**
- * Serializes an XML document.
- * @param aDocument Document to serialize.
- * @return Serialized document.
+ * Serializes an XML document.
+ *
+ * @param aDocument
+ * Document to serialize.
+ * @return Serialized document.
*/
public static String serialize(Document aDocument) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
- serialize(aDocument, os);
- return os.toString();
+ serialize(aDocument, os);
+ return os.toString();
}
-
+
/**
- * Converts a dom4j document into a w3c DOM document.
- * @param aDocument Document to convert.
- * @return W3C DOM document.
+ * Converts a dom4j document into a w3c DOM document.
+ *
+ * @param aDocument
+ * Document to convert.
+ * @return W3C DOM document.
*/
- public static Document convert(org.dom4j.Document aDocument) throws DocumentException {
+ public static Document convert(org.dom4j.Document aDocument)
+ throws DocumentException {
return new DOMWriter().write(aDocument);
}
/**
- * Converts a W3C DOM document into a dom4j document.
- * @param aDocument Document to convert.
+ * Converts a W3C DOM document into a dom4j document.
+ *
+ * @param aDocument
+ * Document to convert.
* @return Dom4j document.
*/
- public static org.dom4j.Document convert(Document aDocument) {
- return new DOMReader().read(aDocument);
+ public static org.dom4j.Document convert(Document aDocument) {
+ return new DOMReader().read(aDocument);
}
-
+
/**
- * Removes duplicate attributes from a DOM tree.This is useful for postprocessing the
- * output of JTidy as a workaround for a bug in JTidy.
+ * Removes duplicate attributes from a DOM tree.This is useful for
+ * postprocessing the output of JTidy as a workaround for a bug in JTidy.
*
* @param aNode
* Node to remove duplicate attributes from (recursively).
for (int i = 0; i < attributes.getLength(); i++) {
Attr attribute = (Attr) attributes.item(i);
if (uniqueAttributes.containsKey(attribute.getNodeName())) {
- System.out.println("Detected duplicate attribute '"
+ LOG.info("Detected duplicate attribute (will be removed)'"
+ attribute.getNodeName() + "'");
}
uniqueAttributes.put(attribute.getNodeName(), attribute);