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

Posted

技术标签:

【中文标题】如何对字符串中的 XML 运行 XQuery?【英文标题】:How do I run an XQuery against XML in a String? 【发布时间】:2013-02-20 10:42:00 【问题描述】:

我有一些 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();
    
  

我遇到的问题是 XML 文档的基本 URI。由于它在内存中,因此没有可参考的基础文档。我知道 XML 将始终是自包含的,因此我决定覆盖 URIResolver 以仅将包装在 Source 类型对象中的 XML 传回。我知道这是错误的,但它有效。如果我不这样做,我会收到 Content not allowed in prolog 错误。从错误消息的其余部分看来,它正在尝试将当前目录作为 XML 文件读取。那部分对我来说有点神秘,但我愿意学习!有没有正确的方法来做我想做的事?

【问题讨论】:

【参考方案1】:

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

"<result>/table/rows/row/cell='Foo2'</result>"

您已经使用 setSource() 提供了上下文项,即使您没有使用它,所以这是您需要进行的唯一更改。

(我还从查询中删除了“/text()”,因为直接测试元素的值要好得多 - 这意味着如果源文档包含 cmets,您的查询仍然有效)。

【讨论】:

啊!因此,对 URI 解析器的调用是因为对 doc("") 的引用。我最初在没有它的情况下编写了查询,但添加它是为了尝试修复我遇到的错误(现在已经忘记了)。它留下来是因为我觉得它改善了一些东西,但现在我看到它是一个红鲱鱼。如果没有对doc() 的引用,我可以删除我冒险的 URIResolver 实现并且一切正常。谢谢,迈克尔。【参考方案2】:

你能做到这一点而不包括封闭并将 xquery 输出放入最终字符串吗?

【讨论】:

以上是关于如何对字符串中的 XML 运行 XQuery?的主要内容,如果未能解决你的问题,请参考以下文章

XPath与Xquery

如何使用 XQuery 获取 XML 文件中的子节点数

如何将XQuery表达式标记为确定性? (为了保留来自XML值的计算列)

使用 XPath/XQuery 过滤 XML 列上的 SQL 查询

在启动我想要运行的完整 XQuery 之前,如何验证嵌入在较大 XQuery 中的 Lucene 查询不包含语法错误?

sql 2005数据库 如何操作xml