/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.xml;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xml.serialize.LineSeparator;
import org.apache.xml.serialize.Method;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.jboss.tools.common.core.CommonCorePlugin;
import org.jboss.tools.common.core.Messages;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class XMLUtilities {
public static boolean hasAttribute(Element e, String s) {
return e.getAttributes().getNamedItem(s) != null;
}
public static Element[] getChildren(Element parent, String name){
ArrayList<Element> al = new ArrayList<Element>();
NodeList nl = parent.getChildNodes();
for (int i = 0; i < nl.getLength(); i++){
Node n = nl.item(i);
if(n.getNodeType() == Node.ELEMENT_NODE &&
n.getNodeName().equals(name)) {
al.add((Element)n);
}
}
return al.toArray(new Element[al.size()]);
}
public static Element getUniqueChild(Element parent, String name){
return getFirstChild(parent, name);
}
public static Element getFirstChild(Element parent, String name) {
NodeList nl = parent.getChildNodes();
for (int i = 0; i < nl.getLength(); i++){
Node n = nl.item(i);
if(n.getNodeType() == Node.ELEMENT_NODE &&
n.getNodeName().equals(name)) {
return (Element)n;
}
}
return null;
}
public static Element getLastChild(Element parent, String name) {
Element child = null;
NodeList nl = parent.getChildNodes();
for (int i = 0; i < nl.getLength(); i++){
Node n = nl.item(i);
if(n.getNodeType() == Node.ELEMENT_NODE &&
n.getNodeName().equals(name)) {
child = (Element)n;
}
}
return child;
}
public static Element[] getAncestors(Element parent, String name) {
int i = name.indexOf('.');
if(i < 0) {
return getChildren(parent, name);
}
Element p = getUniqueChild(parent, name.substring(0, i));
return (p == null) ? new Element[0] : getAncestors(p, name.substring(i + 1));
}
public static Element createElement(Element parent, String path) {
int i = path.indexOf('.');
Element element = null;
if(i < 0) {
element = parent.getOwnerDocument().createElement(path);
parent.appendChild(element);
} else {
String p = path.substring(0, i), c = path.substring(i + 1);
Element pe = getUniqueChild(parent, p);
if(pe == null) {
pe = parent.getOwnerDocument().createElement(p);
parent.appendChild(pe);
}
element = createElement(pe, c);
}
return element;
}
public static DocumentBuilder createDocumentBuilder() {
return createDocumentBuilder(false);
}
public static DocumentBuilder createDocumentBuilder(boolean validate) {
try {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setValidating(validate);
// / f.setExpandEntityReferences(false);
DocumentBuilder d = f.newDocumentBuilder();
if (!validate) {
d.setEntityResolver(EMPTY_RESOLVER);
}
d.setErrorHandler(new ErrorHandlerImpl());
return d;
} catch (ParserConfigurationException e) {
CommonCorePlugin.getPluginLog().logError(e);
}
return null;
}
public static final EntityResolver EMPTY_RESOLVER = createEmptyEntityResolver();
public static Element createDocumentElement(String name) {
Document d = createDocumentBuilder().newDocument();
Element de = d.createElement(name);
d.appendChild(de);
return de;
}
public static EntityResolver createEmptyEntityResolver() {
return new EntityResolver() {
public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId) throws SAXException, java.io.IOException {
if((systemId != null) &&
(systemId.toLowerCase().endsWith(".dtd") || systemId.toLowerCase().endsWith(".ent"))) { // this deactivates DTD //$NON-NLS-1$ //$NON-NLS-2$
return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes())); //$NON-NLS-1$
} else {
return null;
}
}
};
}
public static Element createDocumentElement(String name, String qName, String publicId, String systemId, String namespaceURI) {
Document d = null;
try {
DOMImplementation domImpl = createDocumentBuilder().getDOMImplementation();
DocumentType docType = domImpl.createDocumentType(qName, publicId, systemId);
d = domImpl.createDocument(namespaceURI, name, docType);
} catch (DOMException e) {
return null;
}
Element de = d.getDocumentElement();
if (de == null) {
de = d.createElement(name);
d.appendChild(de);
}
return de;
}
public static Element getElement(String filename, EntityResolver resolver) {
return getElement(new File(filename), resolver);
}
public static Element getElement(File file, EntityResolver resolver) {
if(file == null || !file.isFile()) {
return null;
}
java.io.FileReader fr = null;
try {
fr = new java.io.FileReader(file);
org.xml.sax.InputSource inSource = new org.xml.sax.InputSource(fr);
return getElement(inSource, resolver);
} catch (FileNotFoundException e) {
CommonCorePlugin.getPluginLog().logError(e);
} catch (IOException e) {
CommonCorePlugin.getPluginLog().logError(e);
} catch (SAXException e) {
CommonCorePlugin.getPluginLog().logError(e);
} finally {
try {
if (fr != null) {
fr.close();
}
} catch (IOException e) {
CommonCorePlugin.getPluginLog().logError(e);
}
}
return null;
}
public static Element getElement(Reader reader, EntityResolver resolver) {
Document d = getDocument(reader, resolver);
return (d == null) ? null : d.getDocumentElement();
}
public static Document getDocument(Reader reader, EntityResolver resolver) {
try {
org.xml.sax.InputSource inSource = new org.xml.sax.InputSource(reader);
return getDocument(inSource, resolver);
} catch (SAXException e) {
return null;
} catch (IOException e) {
return null;
}
}
public static Element getElement(InputStream is, EntityResolver resolver) {
try {
org.xml.sax.InputSource inSource = new org.xml.sax.InputSource(is);
return getElement(inSource, resolver);
} catch (SAXException e) {
return null;
} catch (IOException e) {
return null;
}
}
public static Element getElement(InputSource is, EntityResolver resolver) throws SAXException, IOException {
return getDocument(is, resolver).getDocumentElement();
}
public static Document getDocument(InputSource is, EntityResolver resolver) throws SAXException, IOException{
DocumentBuilder builder = createDocumentBuilder(false);
if(resolver != null) {
builder.setEntityResolver(resolver);
}
return builder.parse(is);
}
public static String[] getXMLErrors(Reader reader, EntityResolver resolver) {
return getXMLErrors(reader, true, resolver);
}
public static String[] getXMLErrors(Reader reader, boolean checkDTD, EntityResolver resolver) {
org.xml.sax.InputSource inSource = new org.xml.sax.InputSource(reader);
return getXMLErrors(inSource, checkDTD, resolver);
}
public static String[] getXMLErrors(org.xml.sax.InputSource is, EntityResolver resolver) {
return getXMLErrors(is, true, resolver);
}
public static String[] getXMLErrors(org.xml.sax.InputSource is, boolean checkDTD, EntityResolver resolver) {
ErrorHandlerImpl h = new ErrorHandlerImpl();
try {
DocumentBuilder builder = createDocumentBuilder(checkDTD);
if(resolver != null) {
builder.setEntityResolver(resolver);
}
builder.setErrorHandler(h);
builder.parse(is);
} catch (IOException e) {
if(h.errors.isEmpty()) {
return new String[]{Messages.XMLUtilities_IOExceptionMessage+":0:0",e.toString()}; //$NON-NLS-1$
}
} catch (SAXException e) {
if(h.errors.isEmpty()) {
return new String[]{Messages.XMLUtilities_SAXExceptionMessage+":0:0",e.toString()}; //$NON-NLS-1$
}
}
return h.errors.toArray(new String[h.errors.size()]);
}
public static final void serialize(Element element, String filename) throws IOException {
File f = new File(filename);
if(f.exists() && !f.canWrite()) {
return;
}
if(!f.exists()) {
f.createNewFile();
}
FileWriter fw = new FileWriter(f);
serialize(element, new BufferedWriter(fw));
fw.close();
}
static final String ENCODING = "encoding=\""; //$NON-NLS-1$
static final String UTF8 = "UTF-8"; //$NON-NLS-1$
public static String getEncoding(String body) {
int i = body.indexOf(ENCODING);
if(i < 0) {
return UTF8;
}
i = i + ENCODING.length();
int j = body.indexOf('"', i);
if(j < 0) {
return UTF8;
}
return body.substring(i, j);
}
public static OutputFormat createOutputFormat(String encoding) {
OutputFormat format = new OutputFormat(Method.XML, encoding == null || encoding.length() == 0?null:encoding, true);
format.setLineSeparator(System.getProperty("line.separator", LineSeparator.Web)); //$NON-NLS-1$
format.setIndent(1);
return format;
}
public static final boolean serialize(Element element, Writer w) throws IOException {
if(element == null) {
return false;
}
serialize(element, new XMLSerializer(w, createOutputFormat(UTF8)));
w.close();
return true;
}
public static final boolean serialize(Element element, OutputStream w) throws IOException {
if(element == null) {
return false;
}
serialize(element, new XMLSerializer(w, createOutputFormat(UTF8)));
w.close();
return true;
}
public static void serialize(Element element, XMLSerializer serial) throws IOException {
serial.asDOMSerializer();
serial.serialize(element);
}
public static void serialize(Document document, XMLSerializer serial) throws IOException {
if(serial == null || document == null) {
return;
}
serial.asDOMSerializer();
serial.serialize(document);
}
public static final boolean serialize(Document document, Writer w) throws IOException {
return serialize(document, w, null);
}
public static final boolean serialize(Document document, Writer w, String encoding) throws IOException {
if(document == null) {
return false;
}
serialize(document, new XMLSerializer(w, createOutputFormat(encoding)));
w.close();
return true;
}
public static final String getCDATA(Element elem) {
return getCDATA(elem, true);
}
public static final String getCDATA(Element elem, boolean trim) {
StringBuilder sb = new StringBuilder();
NodeList nl = elem.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node nc = nl.item(i);
if (nc.getNodeType() == Node.CDATA_SECTION_NODE) {
sb.append(((Text) nc).getData());
} else if (nc.getNodeType() == Node.TEXT_NODE) {
String txt = ((Text) nc).getData();
if(trim) {
txt = txt.trim();
}
sb.append(txt);
}
}
return sb.toString();
}
public static final String getComment(Element elem) {
StringBuilder sb = new StringBuilder();
Node node = elem.getPreviousSibling();
while (node != null) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
break;
}
if (node.getNodeType() == Node.COMMENT_NODE) {
if (sb.length() > 0) {
sb.insert(0, '\n');
sb.insert(0, ((Comment) node).getData());
} else {
sb.append(((Comment) node).getData());
}
}
node = node.getPreviousSibling();
}
return sb.toString();
}
public static final void setCDATA(Element element, String data) {
element.appendChild(element.getOwnerDocument().createCDATASection(
data!=null?data:"")); //$NON-NLS-1$
}
public static final void setText(Element element, String data) {
element.appendChild(element.getOwnerDocument().createTextNode(
data!=null?data:"")); //$NON-NLS-1$
}
public static final void setComment(Element element, String data) {
Comment comm = element.getOwnerDocument().createComment(
data!=null?data:""); //$NON-NLS-1$
element.getParentNode().insertBefore(comm, element);
}
}