/* * Copyright (C) 2012 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.metadata; import com.bc.ceres.resource.ReaderResource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringWriter; import java.util.Properties; /** * Handles XPath expressions in velocity template files. The expressions parse an input xml file. * * @author Bettina * @since Ceres 0.13.2 */ public class XPathHandler { /** * Run a XPath query. * Call with $xpath.run("XPath expression", $source-XML) in the velocity template. * e.g. $xpath.run("//creationDate", $metadata) * * @param xpath The XPath expression * @param document Either an instance of {@link ReaderResource}, {@link Element} or a raw xml {@link String}. * @return The demanded information from the XML document. */ public String run(String xpath, Object document) { try { final Document doc = transformToDocument(document); return XPathFactory.newInstance().newXPath().evaluate(xpath, doc); } catch (Exception e) { throw new RuntimeException(e); } } /** * Run a XPath query. * Call with $xpath.run("XPath expression", $source-XML) in the velocity template. * e.g. $xpath.run("//creationDate", $metadata) * * @param xpath The XPath expression * @param document Either an instance of {@link ReaderResource}, {@link Element} or a raw xml {@link String}. * @return The whole XML snippet, which starts with the tag selected in the xpath expression. */ public String extractXml(String xpath, Object document) throws XPathExpressionException { try { final Document doc = transformToDocument(document); final Node node = (Node) XPathFactory.newInstance().newXPath().evaluate(xpath, doc, XPathConstants.NODE); Document newXmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Node copyNode = newXmlDocument.importNode(node, true); newXmlDocument.appendChild(copyNode); return printXmlDocument(newXmlDocument); } catch (Exception e) { throw new RuntimeException(e); } } private static Document transformToDocument(Object document) { try { String docString; if (document instanceof ReaderResource) { docString = ((ReaderResource) document).getContent(); } else if (document instanceof String) { docString = (String) document; } else if (document instanceof Element) { //used? DOMSource domSource = new DOMSource((Element) document); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); Properties properties = new Properties(); properties.setProperty(OutputKeys.METHOD, "xml"); properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperties(properties); transformer.transform(domSource, result); docString = writer.toString(); } else { return null; } InputStream is = new ByteArrayInputStream(docString.getBytes()); return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is); } catch (Exception e) { throw new RuntimeException(e); } } private static String printXmlDocument(Document document) { DOMImplementationLS domImplementationLS = (DOMImplementationLS) document.getImplementation(); LSSerializer lsSerializer = domImplementationLS.createLSSerializer(); String string = lsSerializer.writeToString(document); return string.replace("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n", ""); } }