/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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. */ package org.jkiss.utils.xml; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Common XML utils */ public class XMLUtils { public static Document parseDocument(String fileName) throws XMLException { return parseDocument(new java.io.File(fileName)); } public static Document parseDocument(java.io.File file) throws XMLException { try (InputStream is = new FileInputStream(file)) { return parseDocument(new InputSource(is)); } catch (IOException e) { throw new XMLException("Error opening file '" + file + "'", e); } } public static Document parseDocument(java.io.InputStream is) throws XMLException { return parseDocument(new InputSource(is)); } public static Document parseDocument(java.io.Reader is) throws XMLException { return parseDocument(new InputSource(is)); } public static Document parseDocument(InputSource source) throws XMLException { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder xmlBuilder = dbf.newDocumentBuilder(); return xmlBuilder.parse(source); } catch (Exception er) { throw new XMLException("Error parsing XML document", er); } } public static Document createDocument() throws XMLException { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder xmlBuilder = dbf.newDocumentBuilder(); return xmlBuilder.newDocument(); } catch (Exception er) { throw new XMLException("Error creating XML document", er); } } public static Element getChildElement(Element element, String childName) { for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && ((Element) node).getTagName().equals(childName)) { return (Element) node; } } return null; } @Nullable public static String getChildElementBody(Element element, String childName) { for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && ((Element) node).getTagName().equals(childName)) { return getElementBody((Element) node); } } return null; } @Nullable public static String getElementBody(Element element) { org.w3c.dom.Node valueNode = element.getFirstChild(); if (valueNode == null) { return null; } if (valueNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { return valueNode.getNodeValue(); } else { return null; } } // Get list of all child elements of specified node @NotNull public static List<Element> getChildElementList( Element parent, String nodeName) { List<Element> list = new ArrayList<>(); for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && nodeName.equals(node.getNodeName())) { list.add((Element) node); } } return list; } // Get list of all child elements of specified node @NotNull public static Collection<Element> getChildElementListNS( Element parent, String nsURI) { List<Element> list = new ArrayList<>(); for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && node.getNamespaceURI().equals(nsURI)) { list.add((Element) node); } } return list; } // Get list of all child elements of specified node public static Collection<Element> getChildElementListNS( Element parent, String nodeName, String nsURI) { List<Element> list = new ArrayList<>(); for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE && node.getLocalName().equals(nodeName) && node.getNamespaceURI().equals(nsURI)) { list.add((Element) node); } } return list; } // Get list of all child elements of specified node @NotNull public static Collection<Element> getChildElementList( Element parent, String[] nodeNameList) { List<Element> list = new ArrayList<>(); for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { for (int i = 0; i < nodeNameList.length; i++) { if (node.getNodeName().equals(nodeNameList[i])) { list.add((Element) node); } } } } return list; } // Find one child element with specified name @Nullable public static Element findChildElement( Element parent) { for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { return (Element) node; } } return null; } public static Object escapeXml(Object obj) { if (obj == null) { return null; } else if (obj instanceof CharSequence) { return escapeXml((CharSequence) obj); } else { return obj; } } public static String escapeXml(CharSequence str) { if (str == null) { return null; } StringBuilder res = null; int strLength = str.length(); for (int i = 0; i < strLength; i++) { char c = str.charAt(i); String repl = encodeXMLChar(c); if (repl == null) { if (res != null) { res.append(c); } } else { if (res == null) { res = new StringBuilder(str.length() + 5); for (int k = 0; k < i; k++) { res.append(str.charAt(k)); } } res.append(repl); } } return res == null ? str.toString() : res.toString(); } public static boolean isValidXMLChar(char c) { return (c >= 32 || c == '\n' || c == '\r' || c == '\t'); } /** * Encodes a char to XML-valid form replacing &,',",<,> with special XML encoding. * * @param ch char to convert * @return XML-encoded text */ public static String encodeXMLChar(char ch) { switch (ch) { case '&': return "&"; case '\"': return """; case '\'': return "'"; case '<': return "<"; case '>': return ">"; default: return null; } } public static XMLException adaptSAXException(Exception toCatch) { if (toCatch instanceof XMLException) { return (XMLException) toCatch; } else if (toCatch instanceof org.xml.sax.SAXException) { String message = toCatch.getMessage(); Exception embedded = ((org.xml.sax.SAXException) toCatch).getException(); if (embedded != null && embedded.getMessage() != null && embedded.getMessage().equals(message)) { // Just SAX wrapper - skip it return adaptSAXException(embedded); } else { return new XMLException( message, embedded != null ? adaptSAXException(embedded) : null); } } else { return new XMLException(toCatch.getMessage(), toCatch); } } public static Collection<Element> getChildElementList(Element element) { List<Element> children = new ArrayList<>(); for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { children.add((Element) node); } } return children; } }