package org.araqne.logdb.query.expr;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.araqne.logdb.QueryContext;
import org.araqne.logdb.Row;
import org.araqne.logdb.impl.XmlParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class Xpath extends FunctionExpression {
private final Logger slog = LoggerFactory.getLogger(Xpath.class);
private Expression xmlExpr;
private Expression pathExpr;
public Xpath(QueryContext ctx, List<Expression> exprs) {
super("xpath", exprs, 2);
xmlExpr = exprs.get(0);
pathExpr = exprs.get(1);
}
@Override
public Object eval(Row row) {
Object o1 = xmlExpr.eval(row);
if (o1 == null)
return null;
Object o2 = pathExpr.eval(row);
if (o2 == null)
return null;
String xml = o1.toString();
String path = o2.toString();
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
doc.getDocumentElement().normalize();
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate(path, doc, XPathConstants.NODESET);
int nodeCount = nodes.getLength();
if (nodes.getLength() == 1)
return XmlParser.parseNode(nodes.item(0));
List<Object> l = new ArrayList<Object>(nodeCount);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
l.add(XmlParser.parseNode(node));
}
return l;
} catch (Throwable t) {
if (slog.isDebugEnabled())
slog.debug("araqne logdb: xpath failure", t);
return null;
}
}
}