Java 如何对字符串中的XML运行XQuery?

Java 如何对字符串中的XML运行XQuery?,java,xml,xquery,saxon,Java,Xml,Xquery,Saxon,我有一些XML的字符串表示,我想在内存中对其运行XQuery。我一直在玩撒克逊,并想出了一个解决方案,但为了让它发挥作用,我做了一件丑陋、丑陋的事情。我有一种感觉,那是因为我对撒克逊缺乏经验。以下是一些有效的代码: import javax.xml.transform.URIResolver; import net.sf.saxon.Configuration; import net.sf.saxon.s9api.*; public class XmlTest { public stati

我有一些XML的字符串表示,我想在内存中对其运行XQuery。我一直在玩撒克逊,并想出了一个解决方案,但为了让它发挥作用,我做了一件丑陋、丑陋的事情。我有一种感觉,那是因为我对撒克逊缺乏经验。以下是一些有效的代码:

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();
    }
  }
}
import javax.xml.transform.URIResolver;
导入net.sf.saxon.Configuration;
导入net.sf.saxon.s9api.*;
公共类XML测试{
公共静态void main(字符串[]args){
试一试{
最终字符串tableXml=
"" + 
"  " + 
“FooBar”+
"  " + 
"  " + 
“Foo1Bar1”+
“Foo2Bar2”+
"  " + 
"";
Configuration saxonConfig=新配置();
处理器=新处理器(saxonConfig);
XQueryCompiler XQueryCompiler=processor.newXQueryCompiler();
XQueryExecutable xqueryExec=xqueryCompiler
.compile(“{”
+“doc(“”)/表/行/行/单元格/文本()='Foo2'”
+ "}");
XQueryEvaluator xqueryEval=xqueryExec.load();
xqueryEval.setSource(新SAXSource)(新InputSource(
新的StringReader(tableXml));
XdmDestination destination=新的XdmDestination();
xqueryEval.setDestination(目的地);
//移开你的眼睛!
setURIResolver(新的URIResolver(){
@凌驾
公共源解析(String href,String base)抛出TransformerException{
返回新的StreamSource(新的StringReader(tableXml));
}
});
xqueryEval.run();
System.out.println(destination.getXdmNode());
}捕获(例外e){
e、 printStackTrace();
}
}
}

我遇到的问题是XML文档的基本URI。因为它在内存中,所以没有可引用的基本文档。我知道XML总是自包含的,所以我决定重写
URIResolver
,只传递包装在
类型对象中的XML。我知道这是错误的,但它是有效的。如果我不这样做,我会得到一个prolog中不允许的
内容
错误。从错误消息的其余部分看,它似乎正在尝试将当前目录中的XML文件读取为XML文件。这部分对我来说有点神秘,但我愿意学习!有没有正确的方法来执行我想执行的操作?

如果您想使用doc(“”)访问源文档,那么这就是方法。但是,如果编写查询以作为上下文项的值访问源文档,则会简单得多。所以您将查询更改为

"<result>{/table/rows/row/cell='Foo2'}</result>"
“{/table/rows/row/cell='Foo2'}”
您已经在使用setSource()提供上下文项,即使您没有使用它,因此这是您需要进行的唯一更改


(我还从查询中删除了“/text()”,因为直接测试元素的值要好得多——这意味着如果源文档包含注释,查询仍然可以工作)

您能在不包含封装并仅将xquery输出放入最后一个字符串的情况下做到这一点吗?

啊!因此,调用URI解析器是因为引用了
doc(“”
)。我最初编写查询时没有使用它,但添加它是为了修复我遇到的错误(现在已被遗忘)。它留下来是因为我觉得它改善了一些东西,但现在我发现它是在转移注意力。无需参考
doc()
,我就可以删除dicey URIResolver实现,一切正常。谢谢,迈克尔。