com.day.cq.commons.SimpleXml Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* Copyright 1997-2008 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.cq.commons;
import org.xml.sax.SAXException;
import org.xml.sax.Locator;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerException;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Stack;
/**
* The SimpleXml
class facilitates the creation of an XML document.
*/
public class SimpleXml {
private boolean indentSet;
private boolean encodingSet;
private boolean inited;
private PrintWriter writer;
private TransformerHandler handler;
private Transformer transformer;
private StreamResult result;
private Element currentElement;
private Stack openElements;
/**
* Creates a SimpleXml
instance using the specified
* print writer for the output of the XML document.
* @param w The writer to send the XML document to
* @throws IOException If initialization fails
*/
public SimpleXml(PrintWriter w) throws IOException {
try {
writer = w;
handler = ((SAXTransformerFactory)SAXTransformerFactory.newInstance()).
newTransformerHandler();
result = new StreamResult(writer);
openElements = new Stack();
} catch (TransformerException te) {
throw new IOException(te.getMessage());
}
}
/**
* Returns the print writer used for the output of the XML document.
* @return The print writer
*/
public PrintWriter getWriter() {
return writer;
}
/**
* Defines whether the output should use indetation. Default is
* true
.
* @param indent true
if the output should use indentation,
* false
otherwise
* @return The XML writer
*/
public SimpleXml setIndent(boolean indent) {
getTransformer().setOutputProperty(OutputKeys.INDENT,
indent? "yes" : "no");
indentSet = true;
return this;
}
/**
* Sets the character encoding of the output. Default is UTF-8
.
* @param encoding The character encoding
* @return The XML writer
*/
public SimpleXml setEncoding(String encoding) {
getTransformer().setOutputProperty(OutputKeys.ENCODING,
encoding);
encodingSet = true;
return this;
}
/**
* Defines whether the XML declaration should be omitted. Default is
* false
.
* @param omit true
if the XML declaration should be omitted,
* false
otherwise
* @return The XML writer
*/
public SimpleXml omitXmlDeclaration(boolean omit) {
getTransformer().setOutputProperty(
OutputKeys.OMIT_XML_DECLARATION, omit ? "yes" : "no");
return this;
}
/**
* Sets the document locator of the output.
* @param locator The document locator
* @return The XML writer
*/
public SimpleXml setDocumentLocator(Locator locator) {
handler.setDocumentLocator(locator);
return this;
}
/**
* Opens the XML document. This method is a shorthand for
* {@link #openDocument()}.
* @throws IOException If output fails
* @return The XML writer
*/
public SimpleXml open() throws IOException {
return openDocument();
}
/**
* Opens the XML document.
* @throws IOException If output fails
* @return The XML writer
*/
public SimpleXml openDocument() throws IOException {
if (!"yes".equals(getTransformer().getOutputProperty(
OutputKeys.OMIT_XML_DECLARATION))) {
init();
try {
handler.startDocument();
} catch (SAXException se) {
throw new IOException(se.getMessage());
}
}
return this;
}
/**
* Opens and returns a new XML element with the specified name.
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String name) throws IOException {
return open("", "", name);
}
/**
* Opens and returns a new XML element with the specified name.
* @param localName The local name of the XML element
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String localName, String name) throws IOException {
return open("", localName, name);
}
/**
* Opens and returns a new XML element with the specified name.
* @param uri The URI of the XML element
* @param localName The local name of the XML element
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String uri, String localName, String name)
throws IOException {
startElement(currentElement);
currentElement = openElements.push(new Element(uri, localName, name));
return currentElement;
}
/**
* Opens and returns a new XML element with the specified name and content.
* @param name The name of the XML element
* @param content The content of the XML element
* @param cdata true
if content should be in a CDATA block,
* false
otherwise
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String name, String content, boolean cdata)
throws IOException {
Element element = open("", "", name);
element.setText(content, cdata);
return element;
}
/**
* Closes the XML document after closing all open elements.
* @throws IOException If output fails
*/
public void closeDocument() throws IOException {
tidyUp();
init();
if (!"yes".equals(getTransformer().getOutputProperty(
OutputKeys.OMIT_XML_DECLARATION))) {
try {
handler.endDocument();
} catch (SAXException se) {
throw new IOException(se.getMessage());
}
}
}
/**
* Closes the most recent open element.
* @throws IOException If output fails
* @return The XML writer
*/
public SimpleXml close() throws IOException {
endElement(openElements.pop());
return this;
}
/**
* Closes all currently open elements.
* @throws IOException If output fails
* @return The XML writer
*/
public SimpleXml tidyUp() throws IOException {
while (!openElements.empty()) {
Element element = openElements.pop();
endElement(element);
}
return this;
}
/**
* Initializes the output mechanism and sets defaults.
*/
private void init() {
if (!inited) {
handler.setResult(result);
if (!indentSet) {
setIndent(true);
}
if (!encodingSet) {
setEncoding("utf-8");
}
inited = true;
}
}
/**
* Returns the XML transformer.
* @return The transformer
*/
private Transformer getTransformer() {
if (transformer == null) {
transformer = handler.getTransformer();
}
return transformer;
}
/**
* Starts the output of the specified XML element.
* @param element The XML element
* @throws IOException If output fails
*/
private void startElement(Element element) throws IOException {
if (element == null) {
return;
}
if (!element.isOpened()){
init();
try {
String uri = element.getUri();
String localName = element.getLocalName();
String name = element.getName();
AttributesImpl atts = element.getAttributes();
handler.startElement(uri, localName, name, atts);
} catch (SAXException se) {
throw new IOException(se.getMessage());
}
element.setOpened(true);
}
}
/**
* Ends the output of the specified XML element, removing it from
* the list of open elements.
* @param element The XML element
* @throws IOException If output fails
*/
private void endElement(Element element) throws IOException {
if (element == null) {
return;
}
if (!element.isClosed()) {
startElement(element); // make sure element is started
init();
try {
String uri = element.getUri();
String localName = element.getLocalName();
String name = element.getName();
String content = element.getText();
if (content != null) {
if (element.hasCDATA()) {
handler.startCDATA();
}
handler.characters(content.toCharArray(), 0,
content.length());
if (element.hasCDATA()) {
handler.endCDATA();
}
}
handler.endElement(uri, localName, name);
} catch (SAXException se) {
throw new IOException(se.getMessage());
}
element.setClosed(true);
currentElement = null;
}
openElements.remove(element);
}
/**
* The SimpleXml.Element
reperesents an XML element.
*/
public class Element {
private boolean opened;
private boolean closed;
private boolean cdata;
private AttributesImpl atts;
private String uri;
private String localName;
private String name;
private String text;
/**
* Creates a new SimpleXML.Element
instance using the
* specified URI, local name and name.
* @param uri The URI of the XML element
* @param localName The local name of the XML element
* @param name The name of the XML element
*/
protected Element(String uri, String localName, String name) {
this.uri = uri;
this.localName = localName;
this.name = name;
atts = new AttributesImpl();
}
/**
* Adds a new attribute to the XML element. This method is a shorthand
* for {@link #addAttribute(String, String, String, String, String)}.
* @param name The name of the attribute
* @param value The value of the attribute
* @return The XML element
*/
public Element attr(String name, String value) {
return attr("", "", name, value, "CDATA");
}
/**
* Adds a new attribute to the XML element. This method is a shorthand
* for {@link #addAttribute(String, String, String, String, String)}.
* @param localName The local name of the attribute
* @param name The name of the attribute
* @param value The value of the attribute
* @return The XML element
*/
public Element attr(String localName, String name, String value) {
return attr("", localName, name, value, "CDATA");
}
/**
* Adds a new attribute to the XML element. This method is a shorthand
* for {@link #addAttribute(String, String, String, String, String)}.
* @param uri The URI of the attribute
* @param localName The local name of the attribute
* @param name The name of the attribute
* @param value The value of the attribute
* @param type The type of the attribute
* @return The XML element
*/
public Element attr(String uri, String localName, String name,
String value, String type) {
return addAttribute(uri, localName, name, value, type);
}
/**
* Adds the specified attributes to the XML element.
* @param atts The attributes
* @return The XML element
*/
public Element attrs(String[] ... atts) {
for (int i = 0; i < atts.length; i++) {
attr(atts[i][0], atts[i][1]);
}
return this;
}
/**
* Adds a new attribute to the XML element.
* @param uri The URI of the attribute
* @param localName The local name of the attribute
* @param name The name of the attribute
* @param value The value of the attribute
* @param type The type of the attribute
* @return The XML element
*/
public Element addAttribute(String uri, String localName, String name,
String value, String type) {
if (!opened) {
atts.addAttribute(uri, localName, name, type, value);
}
return this;
}
/**
* Sets the content of the XML element. This method is a shorthand
* for {@link #setText(String, boolean)}.
* @param text The content
* @return The XML element
*/
public Element text(String text) {
return text(text, false);
}
/**
* Sets the content of the XML element. This method is a shorthand
* for {@link #setText(String, boolean)}.
* @param text The content
* @param cdata true
if content should be in a CDATA block,
* false
otherwise
* @return The XML element
*/
public Element text(String text, boolean cdata) {
return setText(text, cdata);
}
/**
* Sets the content of the XML element.
* @param text The content
* @param cdata true
if content should be in a CDATA block,
* false
otherwise
* @return The XML element
*/
public Element setText(String text, boolean cdata) {
if (!closed) {
this.text = text;
this.cdata = cdata;
}
return this;
}
/**
* Defines whether the XML element has a CDATA block.
* @param cdata true
if the XML element has a CDATA block,
* false
otherwise
* @return The XML element
*/
public Element setCDATA(boolean cdata) {
if (!closed) {
this.cdata = cdata;
}
return this;
}
/**
* Explicitly opens the XML element. No more attributes can be added
* to the XML element after calling this method.
* @return The XML writer
* @throws IOException If output fails
*/
public SimpleXml open() throws IOException {
if (!opened) {
startElement(this);
}
return getWriter();
}
/**
* Opens and returns a new XML element with the specified name.
* This method can be used for chaining. It opens the current XML
* element, then calls its equivalent in {@link SimpleXml}.
* @see SimpleXml#open(String)
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String name) throws IOException {
open();
return getWriter().open(name);
}
/**
* Opens and returns a new XML element with the specified name.
* This method can be used for chaining. It opens the current XML
* element, then calls its equivalent in {@link SimpleXml}.
* @see SimpleXml#open(String, String)
* @param localName The local name of the XML element
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String localName, String name) throws IOException {
open();
return getWriter().open(localName, name);
}
/**
* Opens and returns a new XML element with the specified name.
* This method can be used for chaining. It opens the current XML
* element, then calls its equivalent in {@link SimpleXml}.
* @see SimpleXml#open(String, String, String)
* @param uri The URI of the XML element
* @param localName The local name of the XML element
* @param name The name of the XML element
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String uri, String localName, String name)
throws IOException {
open();
return getWriter().open(uri, localName, name);
}
/**
* Opens and returns a new XML element with the specified name and content.
* This method can be used for chaining. It opens the current XML
* element, then calls its equivalent in {@link SimpleXml}.
* @see SimpleXml#open(String, String, boolean)
* @param name The name of the XML element
* @param content The content of the XML element
* @param cdata true
if content should be in a CDATA block,
* false
otherwise
* @return The XML element
* @throws IOException If output fails
*/
public Element open(String name, String content, boolean cdata)
throws IOException {
open();
return getWriter().open(name, content, cdata);
}
/**
* Explicitly closes the XML element. This method will write the
* XML element and consequently render it immutable.
* @return The XML writer
* @throws IOException If output fails
*/
public SimpleXml close() throws IOException {
if (!closed) {
endElement(this);
}
return getWriter();
}
/**
* States whether the XML element has a CDATA block.
* @return true
if the XML element has a CDATA block,
* false
otherwise
*/
public boolean hasCDATA() {
return cdata;
}
/**
* Returns the underlying XML writer
* @return The XML writer
*/
protected SimpleXml getWriter() {
return SimpleXml.this;
}
/**
* States whether the output of the XML element has been started.
* @return true
if the output has been started,
* false
otherwise
*/
protected boolean isOpened() {
return opened;
}
/**
* Defines whether the output of the XML element has been started.
* @param opened true
if the output has been started,
* false
otherwise
*/
protected void setOpened(boolean opened) {
this.opened = opened;
}
/**
* States whether the output of the XML element has been ended.
* @return true
if the output has been ended,
* false
otherwise
*/
protected boolean isClosed() {
return closed;
}
/**
* Defines whether the output of the XML element has been ended.
* @param closed true
if the output has been ended,
* false
otherwise
*/
protected void setClosed(boolean closed) {
this.closed = closed;
}
/**
* Returns the attributes of the XML element.
* @return The attributes
*/
protected AttributesImpl getAttributes() {
return atts;
}
/**
* Returns the URI of the XML element.
* @return The URI
*/
protected String getUri() {
return uri;
}
/**
* Returns the local name of the XML element.
* @return The local name
*/
protected String getLocalName() {
return localName;
}
/**
* Returns the name of the XML element.
* @return The name
*/
protected String getName() {
return name;
}
/**
* Returns the content of the XML element.
* @return The content
*/
protected String getText() {
return text;
}
}
}