com.jamesmurty.utils.XMLBuilder2 Maven / Gradle / Ivy
Show all versions of java-xmlbuilder Show documentation
/*
* Copyright 2008-2020 James Murty (github.com/jmurty)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*
*
* This code is available from the GitHub code repository at:
* https://github.com/jmurty/java-xmlbuilder
*/
package com.jamesmurty.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.Writer;
import java.util.Properties;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* XML Builder is a utility that creates simple XML documents using relatively
* sparse Java code. It is intended to allow for quick and painless creation of
* XML documents where you might otherwise be tempted to use concatenated
* strings, rather than face the tedium and verbosity of coding with
* JAXP (http://jaxp.dev.java.net/).
*
* Internally, XML Builder uses JAXP to build a standard W3C
* {@link org.w3c.dom.Document} model (DOM) that you can easily export as a
* string, or access and manipulate further if you have special requirements.
*
*
* The XMLBuilder2 class serves as a wrapper of {@link org.w3c.dom.Element} nodes,
* and provides a number of utility methods that make it simple to
* manipulate the underlying element and the document to which it belongs.
* In essence, this class performs dual roles: it represents a specific XML
* node, and also allows manipulation of the entire underlying XML document.
* The platform's default {@link DocumentBuilderFactory} and
* {@link DocumentBuilder} classes are used to build the document.
*
*
* XMLBuilder2 has an feature set to the original XMLBuilder, but only ever
* throws runtime exceptions (as opposed to checked exceptions). Any internal
* checked exceptions are caught and wrapped in an
* {@link XMLBuilderRuntimeException} object.
*
*
* @author James Murty
*/
public final class XMLBuilder2 extends BaseXMLBuilder {
/**
* Construct a new builder object that wraps the given XML document.
* This constructor is for internal use only.
*
* @param xmlDocument
* an XML document that the builder will manage and manipulate.
*/
protected XMLBuilder2(Document xmlDocument) {
super(xmlDocument);
}
/**
* Construct a new builder object that wraps the given XML document and node.
* This constructor is for internal use only.
*
* @param myNode
* the XML node that this builder node will wrap. This node may
* be part of the XML document, or it may be a new element that is to be
* added to the document.
* @param parentNode
* If not null, the given myElement will be appended as child node of the
* parentNode node.
*/
protected XMLBuilder2(Node myNode, Node parentNode) {
super(myNode, parentNode);
}
private static RuntimeException wrapExceptionAsRuntimeException(Exception e) {
// Don't wrap (or re-wrap) runtime exceptions.
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new XMLBuilderRuntimeException(e);
}
}
/**
* Construct a builder for new XML document with a default namespace.
* The document will be created with the given root element, and the builder
* returned by this method will serve as the starting-point for any further
* document additions.
*
* @param name
* the name of the document's root element.
* @param namespaceURI
* default namespace URI for document, ignored if null or empty.
* @param enableExternalEntities
* enable external entities; beware of XML External Entity (XXE) injection.
* @param isNamespaceAware
* enable or disable namespace awareness in the underlying
* {@link DocumentBuilderFactory}
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}
*/
public static XMLBuilder2 create(
String name, String namespaceURI, boolean enableExternalEntities,
boolean isNamespaceAware)
{
try {
return new XMLBuilder2(
createDocumentImpl(
name, namespaceURI, enableExternalEntities, isNamespaceAware));
} catch (ParserConfigurationException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* Construct a builder for new XML document. The document will be created
* with the given root element, and the builder returned by this method
* will serve as the starting-point for any further document additions.
*
* @param name
* the name of the document's root element.
* @param enableExternalEntities
* enable external entities; beware of XML External Entity (XXE) injection.
* @param isNamespaceAware
* enable or disable namespace awareness in the underlying
* {@link DocumentBuilderFactory}
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}
*/
public static XMLBuilder2 create(String name,
boolean enableExternalEntities, boolean isNamespaceAware)
{
return XMLBuilder2.create(
name, null, enableExternalEntities, isNamespaceAware);
}
/**
* Construct a builder for new XML document with a default namespace.
* The document will be created with the given root element, and the builder
* returned by this method will serve as the starting-point for any further
* document additions.
*
* @param name
* the name of the document's root element.
* @param namespaceURI
* default namespace URI for document, ignored if null or empty.
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}
*/
public static XMLBuilder2 create(String name, String namespaceURI)
{
return XMLBuilder2.create(name, namespaceURI, false, true);
}
/**
* Construct a builder for new XML document. The document will be created
* with the given root element, and the builder returned by this method
* will serve as the starting-point for any further document additions.
*
* @param name
* the name of the document's root element.
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}
*/
public static XMLBuilder2 create(String name)
{
return XMLBuilder2.create(name, null, false, true);
}
/**
* Construct a builder from an existing XML document. The provided XML
* document will be parsed and an XMLBuilder2 object referencing the
* document's root element will be returned.
*
* @param inputSource
* an XML document input source that will be parsed into a DOM.
* @param enableExternalEntities
* enable external entities; beware of XML External Entity (XXE) injection.
* @param isNamespaceAware
* enable or disable namespace awareness in the underlying
* {@link DocumentBuilderFactory}
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}, {@link SAXException},
* {@link IOException}
*/
public static XMLBuilder2 parse(
InputSource inputSource, boolean enableExternalEntities,
boolean isNamespaceAware)
{
try {
return new XMLBuilder2(
parseDocumentImpl(
inputSource, enableExternalEntities, isNamespaceAware));
} catch (ParserConfigurationException e) {
throw wrapExceptionAsRuntimeException(e);
} catch (SAXException e) {
throw wrapExceptionAsRuntimeException(e);
} catch (IOException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* Construct a builder from an existing XML document string.
* The provided XML document will be parsed and an XMLBuilder2
* object referencing the document's root element will be returned.
*
* @param xmlString
* an XML document string that will be parsed into a DOM.
* @param enableExternalEntities
* enable external entities; beware of XML External Entity (XXE) injection.
* @param isNamespaceAware
* enable or disable namespace awareness in the underlying
* {@link DocumentBuilderFactory}
* @return
* a builder node that can be used to add more nodes to the XML document.
*/
public static XMLBuilder2 parse(
String xmlString, boolean enableExternalEntities, boolean isNamespaceAware)
{
return XMLBuilder2.parse(
new InputSource(new StringReader(xmlString)),
enableExternalEntities,
isNamespaceAware);
}
/**
* Construct a builder from an existing XML document file.
* The provided XML document will be parsed and an XMLBuilder2
* object referencing the document's root element will be returned.
*
* @param xmlFile
* an XML document file that will be parsed into a DOM.
* @param enableExternalEntities
* enable external entities; beware of XML External Entity (XXE) injection.
* @param isNamespaceAware
* enable or disable namespace awareness in the underlying
* {@link DocumentBuilderFactory}
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}, {@link SAXException},
* {@link IOException}, {@link FileNotFoundException}
*/
public static XMLBuilder2 parse(File xmlFile, boolean enableExternalEntities,
boolean isNamespaceAware)
{
try {
return XMLBuilder2.parse(
new InputSource(new FileReader(xmlFile)),
enableExternalEntities,
isNamespaceAware);
} catch (FileNotFoundException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* Construct a builder from an existing XML document. The provided XML
* document will be parsed and an XMLBuilder2 object referencing the
* document's root element will be returned.
*
* @param inputSource
* an XML document input source that will be parsed into a DOM.
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}, {@link SAXException},
* {@link IOException}
*/
public static XMLBuilder2 parse(InputSource inputSource)
{
return XMLBuilder2.parse(inputSource, false, true);
}
/**
* Construct a builder from an existing XML document string.
* The provided XML document will be parsed and an XMLBuilder2
* object referencing the document's root element will be returned.
*
* @param xmlString
* an XML document string that will be parsed into a DOM.
* @return
* a builder node that can be used to add more nodes to the XML document.
*/
public static XMLBuilder2 parse(String xmlString)
{
return XMLBuilder2.parse(xmlString, false, true);
}
/**
* Construct a builder from an existing XML document file.
* The provided XML document will be parsed and an XMLBuilder2
* object referencing the document's root element will be returned.
*
* @param xmlFile
* an XML document file that will be parsed into a DOM.
* @return
* a builder node that can be used to add more nodes to the XML document.
* @throws XMLBuilderRuntimeException
* to wrap {@link ParserConfigurationException}, {@link SAXException},
* {@link IOException}, {@link FileNotFoundException}
*/
public static XMLBuilder2 parse(File xmlFile)
{
return XMLBuilder2.parse(xmlFile, false, true);
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link XPathExpressionException}
*/
@Override
public XMLBuilder2 stripWhitespaceOnlyTextNodes()
{
try {
super.stripWhitespaceOnlyTextNodesImpl();
return this;
} catch (XPathExpressionException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
@Override
public XMLBuilder2 importXMLBuilder(BaseXMLBuilder builder) {
super.importXMLBuilderImpl(builder);
return this;
}
@Override
public XMLBuilder2 root() {
return new XMLBuilder2(getDocument());
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link XPathExpressionException}
*/
@Override
public XMLBuilder2 xpathFind(String xpath, NamespaceContext nsContext)
{
try {
Node foundNode = super.xpathFindImpl(xpath, nsContext);
return new XMLBuilder2(foundNode, null);
} catch (XPathExpressionException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
@Override
public XMLBuilder2 xpathFind(String xpath) {
return xpathFind(xpath, null);
}
@Override
public XMLBuilder2 element(String name) {
String namespaceURI = super.lookupNamespaceURIImpl(name);
return element(name, namespaceURI);
}
@Override
public XMLBuilder2 elem(String name) {
return element(name);
}
@Override
public XMLBuilder2 e(String name) {
return element(name);
}
@Override
public XMLBuilder2 element(String name, String namespaceURI) {
Element elem = super.elementImpl(name, namespaceURI);
return new XMLBuilder2(elem, this.getElement());
}
@Override
public XMLBuilder2 elementBefore(String name) {
Element newElement = super.elementBeforeImpl(name);
return new XMLBuilder2(newElement, null);
}
@Override
public XMLBuilder2 elementBefore(String name, String namespaceURI) {
Element newElement = super.elementBeforeImpl(name, namespaceURI);
return new XMLBuilder2(newElement, null);
}
@Override
public XMLBuilder2 attribute(String name, String value) {
super.attributeImpl(name, value);
return this;
}
@Override
public XMLBuilder2 attr(String name, String value) {
return attribute(name, value);
}
@Override
public XMLBuilder2 a(String name, String value) {
return attribute(name, value);
}
@Override
public XMLBuilder2 text(String value, boolean replaceText) {
super.textImpl(value, replaceText);
return this;
}
@Override
public XMLBuilder2 text(String value) {
return this.text(value, false);
}
@Override
public XMLBuilder2 t(String value) {
return text(value);
}
@Override
public XMLBuilder2 cdata(String data) {
super.cdataImpl(data);
return this;
}
@Override
public XMLBuilder2 data(String data) {
return cdata(data);
}
@Override
public XMLBuilder2 d(String data) {
return cdata(data);
}
@Override
public XMLBuilder2 cdata(byte[] data) {
super.cdataImpl(data);
return this;
}
@Override
public XMLBuilder2 data(byte[] data) {
return cdata(data);
}
@Override
public XMLBuilder2 d(byte[] data) {
return cdata(data);
}
@Override
public XMLBuilder2 comment(String comment) {
super.commentImpl(comment);
return this;
}
@Override
public XMLBuilder2 cmnt(String comment) {
return comment(comment);
}
@Override
public XMLBuilder2 c(String comment) {
return comment(comment);
}
@Override
public XMLBuilder2 instruction(String target, String data) {
super.instructionImpl(target, data);
return this;
}
@Override
public XMLBuilder2 inst(String target, String data) {
return instruction(target, data);
}
@Override
public XMLBuilder2 i(String target, String data) {
return instruction(target, data);
}
@Override
public XMLBuilder2 insertInstruction(String target, String data) {
super.insertInstructionImpl(target, data);
return this;
}
@Override
public XMLBuilder2 reference(String name) {
super.referenceImpl(name);
return this;
}
@Override
public XMLBuilder2 ref(String name) {
return reference(name);
}
@Override
public XMLBuilder2 r(String name) {
return reference(name);
}
@Override
public XMLBuilder2 namespace(String prefix, String namespaceURI) {
super.namespaceImpl(prefix, namespaceURI);
return this;
}
@Override
public XMLBuilder2 ns(String prefix, String namespaceURI) {
return namespace(prefix, namespaceURI);
}
@Override
public XMLBuilder2 namespace(String namespaceURI) {
this.namespace(null, namespaceURI);
return this;
}
@Override
public XMLBuilder2 ns(String namespaceURI) {
return namespace(namespaceURI);
}
@Override
public XMLBuilder2 up(int steps) {
Node currNode = super.upImpl(steps);
if (currNode instanceof Document) {
return new XMLBuilder2((Document) currNode);
} else {
return new XMLBuilder2(currNode, null);
}
}
@Override
public XMLBuilder2 up() {
return up(1);
}
@Override
public XMLBuilder2 document() {
return new XMLBuilder2(getDocument(), null);
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public String asString() {
try {
return super.asString();
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public String asString(Properties properties) {
try {
return super.asString(properties);
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public String elementAsString() {
try {
return super.elementAsString();
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public String elementAsString(Properties outputProperties) {
try {
return super.elementAsString(outputProperties);
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public void toWriter(boolean wholeDocument, Writer writer, Properties outputProperties)
{
try {
super.toWriter(wholeDocument, writer, outputProperties);
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link TransformerException}
*
*/
@Override
public void toWriter(Writer writer, Properties outputProperties)
{
try {
super.toWriter(writer, outputProperties);
} catch (TransformerException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link XPathExpressionException}
*
*/
@Override
public Object xpathQuery(String xpath, QName type, NamespaceContext nsContext)
{
try {
return super.xpathQuery(xpath, type, nsContext);
} catch (XPathExpressionException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
/**
* @throws XMLBuilderRuntimeException
* to wrap {@link XPathExpressionException}
*
*/
@Override
public Object xpathQuery(String xpath, QName type)
{
try {
return super.xpathQuery(xpath, type);
} catch (XPathExpressionException e) {
throw wrapExceptionAsRuntimeException(e);
}
}
}