我有一些XML的String表示,我想在内存中运行XQuery。我一直在玩Saxon并想出一个解决方案,但是为了让它起作用,我做了一个丑陋,丑陋的事情。我有一种感觉,因为我缺乏与撒克逊人的经验。以下是一些有效的代码:
import javax.xml.transform.URIResolver;
import net.sf.saxon.Configuration;
import net.sf.saxon.s9api.*;
public class XmlTest {
public static void main(String[] args) {
try {
final String tableXml =
"<table>" +
" <columns>" +
" <column>Foo</column><column>Bar</column>" +
" </columns>" +
" <rows>" +
" <row><cell>Foo1</cell><cell>Bar1</cell></row>" +
" <row><cell>Foo2</cell><cell>Bar2</cell></row>" +
" </rows>" +
"</table>";
Configuration saxonConfig = new Configuration();
Processor processor = new Processor(saxonConfig);
XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();
XQueryExecutable xqueryExec = xqueryCompiler
.compile("<result>{"
+ "doc('')/table/rows/row/cell/text()='Foo2'"
+ "}</result>");
XQueryEvaluator xqueryEval = xqueryExec.load();
xqueryEval.setSource(new SAXSource(new InputSource(
new StringReader(tableXml))));
XdmDestination destination = new XdmDestination();
xqueryEval.setDestination(destination);
// Avert your eyes!
xqueryEval.setURIResolver(new URIResolver() {
@Override
public Source resolve(String href, String base) throws TransformerException {
return new StreamSource(new StringReader(tableXml));
}
});
xqueryEval.run();
System.out.println(destination.getXdmNode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
我遇到的问题是XML文档的基URI。由于它是在内存中,因此没有可供参考的基础文档。我知道XML将始终是自包含的,因此我决定覆盖URIResolver
以仅传回包含在Source
类型对象中的XML。我知道这是错的,但它确实有效。如果我不这样做,我会收到Content not allowed in prolog
错误。从错误消息的其余部分看,它似乎正在尝试将当前目录作为XML文件读取。那部分对我来说有点神秘,但我愿意学习!有没有正确的方法来做我想做的事情?
答案 0 :(得分:4)
如果要使用doc('')访问源文档,则可以使用此方法。但是,如果您将查询编写为访问源文档作为上下文项的值,则会更加简单。因此,您将查询更改为
"<result>{/table/rows/row/cell='Foo2'}</result>"
您已经使用setSource()提供了上下文项,即使您没有使用它,因此这是您需要进行的唯一更改。
(我还从查询中删除了“/ text()”,因为直接测试元素的值要好得多 - 这意味着如果源文档包含注释,您的查询仍然有效)。
答案 1 :(得分:0)
你可以在不包括封闭并将xquery输出放入最终字符串的情况下执行此操作吗?