import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.stream.StreamSource; import org.basex.build.xml.XMLParser; import org.basex.core.MainOptions; import org.basex.io.IO; import org.basex.query.value.node.DBNode; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import net.sf.saxon.Configuration; import net.sf.saxon.expr.XPathContext; import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.lib.ExtensionFunctionDefinition; import net.sf.saxon.lib.Initializer; import net.sf.saxon.lib.ParseOptions; import net.sf.saxon.om.Sequence; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.om.TreeInfo; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.SequenceType; public class XQueryParser { public static Element parseXQueryToDOM(String input) throws Exception { DOMBuilder domBuilder = new DOMBuilder(); CR_xquery_31_20151217 parser = new CR_xquery_31_20151217(input, domBuilder); try { parser.parse_XQuery(); return domBuilder.getResult(); } catch (CR_xquery_31_20151217.ParseException e) { throw new RuntimeException(parser.getErrorMessage(e)); } } public static DBNode parseXQueryToDBNode(String input) throws Exception { String xml = parseXQueryToXml(input); XMLParser xmlParser = new XMLParser(IO.get(xml), MainOptions.get()); return new DBNode(xmlParser); } public static String parseXQueryToXml(String input) throws Exception { ByteArrayOutputStream output = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(output, "UTF-8"); CR_xquery_31_20151217.XmlSerializer serializer = new CR_xquery_31_20151217.XmlSerializer(writer); CR_xquery_31_20151217 parser = new CR_xquery_31_20151217(input, serializer); try { parser.parse_XQuery(); writer.close(); String xmlOutput = new String(output.toByteArray(), "UTF-8"); return xmlOutput; } catch (CR_xquery_31_20151217.ParseException pe) { throw new RuntimeException(parser.getErrorMessage(pe)); } } public static class SaxonInitializer implements Initializer { @Override public void initialize(Configuration conf) { conf.registerExtensionFunction(new ParseXQueryToNodeInfo()); } } public static class ParseXQueryToNodeInfo extends ExtensionFunctionDefinition { @Override public StructuredQName getFunctionQName() {return new StructuredQName("p", "XQueryParser", "parseXQueryToNodeInfo");} @Override public SequenceType[] getArgumentTypes() {return new SequenceType[] {SequenceType.SINGLE_STRING};} @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {return SequenceType.SINGLE_ELEMENT_NODE;} @Override public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { try { String input = arguments[0].iterate().next().getStringValue(); String output = parseXQueryToXml(input); StreamSource source = new StreamSource(new StringReader(output)); TreeInfo document = context.getConfiguration().buildDocumentTree(source, new ParseOptions()); return document.getRootNode(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } }; } } private static class DOMBuilder implements CR_xquery_31_20151217.EventHandler { private DocumentBuilder documentBuilder; private Document document; private Node current; private CharSequence input; public DOMBuilder() throws Exception { documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } public Element getResult() { return document.getDocumentElement(); } @Override public void reset(CharSequence input) { this.input = input; document = documentBuilder.newDocument(); current = document; } @Override public void startNonterminal(String name, int begin) { Element nonterminal = document.createElement(name); current.appendChild(nonterminal); current = nonterminal; } @Override public void endNonterminal(String name, int end) { current = current.getParentNode(); } @Override public void terminal(String name, int begin, int end) { if (name.startsWith("'") || name.startsWith("\"")) name = "TOKEN"; Element terminal = document.createElement(name); terminal.appendChild(document.createTextNode(input.subSequence(begin, end).toString())); current.appendChild(terminal); } @Override public void whitespace(int begin, int end) { current.appendChild(document.createTextNode(input.subSequence(begin, end).toString())); } } }