com.elsevier.xml.XQueryProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.elsevier.xml.XQueryProcessor.java

Source

/*
 * Copyright (c)2015 Elsevier, Inc.
    
 * 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 com.elsevier.xml;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;

import javax.xml.transform.stream.StreamSource;

import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Class with static methods to apply an XQuery expression against a string of
 * arbitrary xml content.
 * 
 * @author Darin McBeath
 * 
 */
public class XQueryProcessor {

    // Logger
    private static Log log = LogFactory.getLog(XQueryProcessor.class);

    /**
     * Init the NamespaceContext. Set the prefix to namespace mappings specified 
     * in the passed HashMap.  
     * 
     * @param prefixesNamespaces HashMap of namespace prefix / namespace uri mappings
        
     */
    public static void init(HashMap<String, String> prefixesNamespaces) throws IOException {

        NamespaceContextMappings.init(prefixesNamespaces);

    }

    /**
     * Clear namespace prefix / namespace uri mappings. Useful if you want to use a 
     * different set of prefix/namespace mappings.
     */
    public static void clear() {

        NamespaceContextMappings.emptyCache();

    }

    /**
     * Apply the xqueryExpression to the specified string and return a
     * serialized response.
     * 
     * @param content
     *            String to which the xqueryExpression will be applied
     * @param xqueryExpression
     *            XQuery expression to apply to the content
     * 
     * @return Serialized response from the evaluation. If an error, the response will be "<error/>".
     */
    public static String evaluateString(String content, String xqueryExpression) {

        try {

            return evaluate(new StreamSource(IOUtils.toInputStream(content, CharEncoding.UTF_8)), xqueryExpression);

        } catch (IOException e) {

            log.error("Problems processing the content.  " + e.getMessage(), e);
            return "<error/>";

        }

    }

    /**
     * Apply xqueryExpression to the content and return a serialized response
     * 
     * @param content
     *            StreamSource of content for which the xqueryExpression will be
     *            applied
     * @param xqueryExpression
     *            XQuery expression to apply agains the content
     * @return Serialized response from the evaluation
     * @throws IOException 
     */
    private static String evaluate(StreamSource content, String xqueryExpression) throws IOException {

        try {

            // Get the processor
            Processor proc = new Processor(false);

            // Compile the xquery
            XQueryCompiler xqueryCompiler = proc.newXQueryCompiler();
            xqueryCompiler.setEncoding(CharEncoding.UTF_8);

            // Set the namespace to prefix mappings
            setPrefixNamespaceMappings(xqueryCompiler);

            XQueryExecutable exp = xqueryCompiler.compile(xqueryExpression);

            // Get the evaluator, set the source (content)
            XQueryEvaluator eval = exp.load();
            eval.setSource(content);

            // Create an output serializer
            Serializer out = new Serializer();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            out.setOutputStream(baos);
            // Appears ok to always set output property to xml (even if we are just returning a text string)
            out.setOutputProperty(Serializer.Property.METHOD, "xml");
            out.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            out.setProcessor(proc);

            // Run the query
            eval.run(out);

            // Return the results
            return new String(baos.toByteArray(), CharEncoding.UTF_8);

        } catch (IOException e) {

            log.error("Problems processing the content.  EXPRESSION:" + xqueryExpression + " " + e.getMessage(), e);
            return "<error/>";

        } catch (SaxonApiException e) {

            log.error("Problems processing the content.  EXPRESSION:" + xqueryExpression + " " + e.getMessage(), e);
            return "<error/>";

        }

    }

    /**
     * Set the namespaces in the XQueryCompiler.
     * 
     * @param xqueryCompiler
     */
    private static void setPrefixNamespaceMappings(XQueryCompiler xqueryCompiler) {

        // Get the mappings
        Set<Entry<String, String>> mappings = NamespaceContextMappings.getMappings();

        // If mappings exist, set the namespaces
        if (mappings != null) {
            synchronized (XQueryProcessor.class) {
                if (mappings != null) {
                    Iterator<Entry<String, String>> it = mappings.iterator();
                    while (it.hasNext()) {
                        Entry<String, String> entry = it.next();
                        xqueryCompiler.declareNamespace(entry.getKey(), entry.getValue());
                    }
                }
            }
        }

    }

}