out-xpath: support also node-set (not only primitive type results)
authorFrantišek Kučera <franta-hg@frantovo.cz>
Wed, 29 Oct 2014 01:25:06 +0100
changeset 105e62a3e498212
parent 104 33b2441a6d36
child 106 02739f60b1ec
out-xpath: support also node-set (not only primitive type results)
java/alt2xml-out-xpath/src/cz/frantovo/alt2xml/out/xpath/XPathAction.java
     1.1 --- a/java/alt2xml-out-xpath/src/cz/frantovo/alt2xml/out/xpath/XPathAction.java	Tue Oct 28 17:53:24 2014 +0100
     1.2 +++ b/java/alt2xml-out-xpath/src/cz/frantovo/alt2xml/out/xpath/XPathAction.java	Wed Oct 29 01:25:06 2014 +0100
     1.3 @@ -21,17 +21,32 @@
     1.4  import cz.frantovo.alt2xml.out.ActionContext;
     1.5  import cz.frantovo.alt2xml.out.OutputActionException;
     1.6  import java.io.PrintWriter;
     1.7 +import java.io.StringWriter;
     1.8  import java.util.Arrays;
     1.9  import java.util.HashMap;
    1.10  import java.util.List;
    1.11  import java.util.Map;
    1.12 +import java.util.logging.Level;
    1.13 +import java.util.logging.Logger;
    1.14 +import javax.xml.transform.OutputKeys;
    1.15 +import javax.xml.transform.Transformer;
    1.16 +import javax.xml.transform.TransformerConfigurationException;
    1.17 +import javax.xml.transform.TransformerException;
    1.18 +import javax.xml.transform.TransformerFactory;
    1.19 +import javax.xml.transform.TransformerFactoryConfigurationError;
    1.20  import javax.xml.transform.dom.DOMResult;
    1.21 +import javax.xml.transform.dom.DOMSource;
    1.22 +import javax.xml.transform.stream.StreamResult;
    1.23  import javax.xml.xpath.XPath;
    1.24 +import javax.xml.xpath.XPathConstants;
    1.25  import javax.xml.xpath.XPathExpression;
    1.26  import javax.xml.xpath.XPathExpressionException;
    1.27  import javax.xml.xpath.XPathFactory;
    1.28  import javax.xml.xpath.XPathVariableResolver;
    1.29 +import org.w3c.dom.Attr;
    1.30 +import org.w3c.dom.Element;
    1.31  import org.w3c.dom.Node;
    1.32 +import org.w3c.dom.NodeList;
    1.33  
    1.34  /**
    1.35   *
    1.36 @@ -42,9 +57,14 @@
    1.37  	public static final String PARAMETER_TYPED_PARAMETERS = "typed-parameters";
    1.38  	public static final String PARAMETER_LINE_BREAK = "line-break";
    1.39  	public static final String PARAMETER_ENVIRONMENT_VARIABLES = "environment-variables";
    1.40 +	public static final String PARAMETER_NODE_SET = "node-set";
    1.41 +	private static final Logger log = Logger.getLogger(XPathAction.class.getName());
    1.42  	private final boolean typedParameters;
    1.43  	private final boolean lineBreak;
    1.44  	private final boolean environmentVariables;
    1.45 +	private final boolean nodeSet;
    1.46 +	private final TransformerFactory transformerFactory;
    1.47 +	private final Transformer copyTransformer;
    1.48  	private final XPathFactory xpathFactory;
    1.49  	private final XPath xpath;
    1.50  	private final String expressionString;
    1.51 @@ -54,6 +74,14 @@
    1.52  		xpathFactory = XPathFactory.newInstance();
    1.53  		xpath = xpathFactory.newXPath();
    1.54  
    1.55 +		try {
    1.56 +			transformerFactory = TransformerFactory.newInstance();
    1.57 +			copyTransformer = transformerFactory.newTransformer();
    1.58 +			copyTransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    1.59 +		} catch (TransformerConfigurationException | TransformerFactoryConfigurationError e) {
    1.60 +			throw new OutputActionException("Unable to initialize XSLT copying transformer", e);
    1.61 +		}
    1.62 +
    1.63  		final List<String> actionData = getActionContext().getActionData();
    1.64  
    1.65  		if (actionData.size() < 1) {
    1.66 @@ -63,6 +91,7 @@
    1.67  			typedParameters = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_TYPED_PARAMETERS));
    1.68  			lineBreak = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_LINE_BREAK, Boolean.TRUE.toString()));
    1.69  			environmentVariables = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_ENVIRONMENT_VARIABLES, Boolean.FALSE.toString()));
    1.70 +			nodeSet = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_NODE_SET, Boolean.FALSE.toString()));
    1.71  
    1.72  			Map<String, Object> xpathParameters = new HashMap<>();
    1.73  
    1.74 @@ -139,6 +168,16 @@
    1.75  		}
    1.76  	}
    1.77  
    1.78 +	private String nodeToString(Node node) throws OutputActionException {
    1.79 +		try {
    1.80 +			StringWriter w = new StringWriter();
    1.81 +			copyTransformer.transform(new DOMSource(node), new StreamResult(w));
    1.82 +			return w.toString();
    1.83 +		} catch (TransformerException e) {
    1.84 +			throw new OutputActionException("Unable to convert node to string", e);
    1.85 +		}
    1.86 +	}
    1.87 +
    1.88  	@Override
    1.89  	public void run(DOMResult domResult) throws OutputActionException {
    1.90  		XPathExpression xpathExpression = null;
    1.91 @@ -153,12 +192,42 @@
    1.92  				throw new OutputActionException("Unable to compile XPath: " + expressionString, e);
    1.93  			}
    1.94  
    1.95 -			String result = xpathExpression.evaluate(document);
    1.96  			try (PrintWriter out = new PrintWriter(getActionContext().getOutputStream())) {
    1.97 -				out.print(result);
    1.98 -				if (lineBreak) {
    1.99 -					out.println();
   1.100 +
   1.101 +				if (nodeSet) {
   1.102 +					NodeList result = (NodeList) xpathExpression.evaluate(document, XPathConstants.NODESET);
   1.103 +					for (int i = 0; i < result.getLength(); i++) {
   1.104 +						Node node = result.item(i);
   1.105 +
   1.106 +						log.log(Level.FINE, "Node type: {0}", node.getClass());
   1.107 +
   1.108 +						final String stringValue;
   1.109 +
   1.110 +						if (node instanceof Attr) {
   1.111 +							Attr attribute = (Attr) node;
   1.112 +							stringValue = attribute.getValue();
   1.113 +						} else if (node instanceof Element) {
   1.114 +							stringValue = nodeToString(node);
   1.115 +							/**
   1.116 +							 * TODO: print/log node separator
   1.117 +							 */
   1.118 +						} else {
   1.119 +							stringValue = String.valueOf(node);
   1.120 +						}
   1.121 +
   1.122 +						out.print(stringValue);
   1.123 +						if (lineBreak) {
   1.124 +							out.println();
   1.125 +						}
   1.126 +					}
   1.127 +				} else {
   1.128 +					log.log(Level.FINE, "String value, no node-set");
   1.129 +					out.print(xpathExpression.evaluate(document));
   1.130 +					if (lineBreak) {
   1.131 +						out.println();
   1.132 +					}
   1.133  				}
   1.134 +
   1.135  			}
   1.136  		} catch (XPathExpressionException e) {
   1.137  			throw new OutputActionException("Unable to evaluate XPath: " + xpathExpression, e);