/******************************************************************************* * 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); } }