package eu.dnetlib.ariadneplus.publisher; import java.io.StringReader; import java.util.Map; import java.util.Map.Entry; import javax.xml.transform.sax.SAXSource; import com.google.common.collect.Maps; import net.sf.saxon.s9api.*; import net.sf.saxon.s9api.Serializer.Property; import org.springframework.stereotype.Component; import org.xml.sax.InputSource; /** * @author enrico.ottonello * */ @Component public class SaxonHelper { private Processor xmlProcessor = new Processor(false); public Helper help(){ return new Helper(); } public class Helper{ private Serializer serializer; Helper() { this.serializer = xmlProcessor.newSerializer(); serializer.setOutputProperty(Property.METHOD, "xml"); serializer.setOutputProperty(Property.INDENT, "yes"); } public Helper setSerializerProperty(Property p, String value){ serializer.setOutputProperty(p, value); return this; } public XdmNode parseXML(final String xmlSource) throws SaxonApiException { SAXSource source = new SAXSource(new InputSource(new StringReader(xmlSource))); DocumentBuilder docBuilder = xmlProcessor.newDocumentBuilder(); return docBuilder.build(source); } /** * Evaluate the given xpath on the given XML source. * * @param xmlSource XML source string * @param xpath the xpath to evaluate * @param namespaces the map of namespaces to be declared to evaluate the xpath * @return an XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. */ public XdmItem evaluateSingle(final String xmlSource, final String xpath, final Map namespaces) throws SaxonApiException { XPathSelector xpathSelector = prepareXPathSelector(xpath, namespaces); return evaluateSingle(xmlSource, xpathSelector); } /** * Applies the given xpath selector on the given XML source. * * @param xmlSource XML source string * @param xpathSelector the configured xpath selector to apply * @return an XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. */ public XdmItem evaluateSingle(final String xmlSource, final XPathSelector xpathSelector) throws SaxonApiException { XdmNode xdmNode = parseXML(xmlSource); xpathSelector.setContextItem(xdmNode); return xpathSelector.evaluateSingle(); } /** * Get an XPathSelector for the given xpath and namespaces. * @param xpath the xpath * @param namespaces the map of namespaces to be declared to evaluate the xpath * @return XPathSelector * @throws SaxonApiException */ public XPathSelector prepareXPathSelector(final String xpath,final Map namespaces) throws SaxonApiException { XPathCompiler compiler = xmlProcessor.newXPathCompiler(); for (Entry ns : namespaces.entrySet()) { compiler.declareNamespace(ns.getKey(), ns.getValue()); } XPathExecutable xpathExecutable = compiler.compile(xpath); XPathSelector xpathSelector = xpathExecutable.load(); return xpathSelector; } /** * Get an XPathSelector for the given xpath and namespaces. * @param xpath the xpath * @param nsPrefix namespace prefix * @param ns namespace URI * @return XPathSelector * @throws SaxonApiException */ public XPathSelector prepareXPathSelector(final String xpath,final String nsPrefix, final String ns) throws SaxonApiException { Map map = Maps.newHashMap(); map.put(nsPrefix, ns); return prepareXPathSelector(xpath, map); } /** * Evaluate the given xpath on the given XML source. * @param xmlSource XML source string * @param xpath the xpath to evaluate * @param nsPrefix namespace prefix * @param ns namespace URI * @return an XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. * @throws SaxonApiException * */ public XdmItem evaluateSingle(final String xmlSource, final String xpath, final String nsPrefix, final String ns) throws SaxonApiException { Map map = Maps.newHashMap(); map.put(nsPrefix, ns); return evaluateSingle(xmlSource, xpath, map); } /** * Evaluate the given xpath on the given XML source. * * @param xmlSource XML source string * @param xpath the xpath to evaluate. xpath must evaluate to an xdmNode * @param namespaces the map of namespaces to be declared to evaluate the xpath * @return the XML serialization as string of the XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. * @throws ClassCastException if xpath is not evaluated to a node. */ public String evaluateSingleAsString(final String xmlSource, final String xpath, final Map namespaces) throws SaxonApiException { XdmItem item = evaluateSingle(xmlSource, xpath, namespaces); if(item != null){ XdmNode node = (XdmNode) item; return serializer.serializeNodeToString(node); } else return null; } /** * Applies the given xpath selector on the given XML source. * * @param xmlSource XML source string * @param xpathSelector the configured xpath selector to apply * @return the XML serialization as string of the XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. * @throws ClassCastException if xpath is not evaluated to a node. */ public String evaluateSingleAsString(final String xmlSource, final XPathSelector xpathSelector) throws SaxonApiException { XdmItem item = evaluateSingle(xmlSource, xpathSelector); if(item != null){ XdmNode node = (XdmNode) item; return serializer.serializeNodeToString(node); } else return null; } /** * Evaluate the given xpath on the given XML source. * * @param xmlSource XML source string * @param xpath the xpath to evaluate. xpath must evaluate to an xdmNode * @param nsPrefix namespace prefix * @param ns namespace URI * @return the XML serialization as string of the XdmItem resulting from the evaluation of the xpath. Returns null if nothing matches. * @throws ClassCastException if xpath is not evaluated to a node. */ public String evaluateSingleAsString(final String xmlSource, final String xpath, final String nsPrefix, final String ns) throws SaxonApiException { Map map = Maps.newHashMap(); map.put(nsPrefix, ns); return evaluateSingleAsString(xmlSource, xpath, map); } } }