Saxon HE 9.7 XQuery结果和现有文档

时间:2016-08-11 03:44:01

标签: xquery saxon

我是Saxon的新手。

在我的java应用程序中,我要求我需要XQuery一个现有的dom4j文档。 XQuery是通过serialNo:

按降序排序少数元素
<?xml version="1.0" encoding="UTF-8"?>
<dataOfBooks:DataOfBooks xmlns:dataOfBooks="DataOfBooks">
  <Id>ID123</Id>
  <books>
    <book>
      <name>ccc</name>
      <serialNo>77</serialNo>
    </book>
    <book>
      <name>aaa</name>
      <serialNo>99</serialNo>
    </book>
  </books>
</dataOfBooks:DataOfBooks>

获得XQuery结果后,我需要将这些结果添加回上述现有文档。我尝试使用net.sf.saxon.s9api。我能够将XQuery结果恢复如下:

<?xml version="1.0" encoding="UTF-8"?>
<result:sequence
  xmlns:result="http://saxon.sf.net/xquery-results"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <result:element>
    <book xmlns:data="dataOfBooks">
      <name>aaa</name>
      <serialNo>99</serialNo>
    </book>
    <book xmlns:data="dataOfBooks">
      <name>aaa</name>
      <serialNo>77</serialNo>
    </book>
  </result:element>
</result:sequence>

但我有两个问题。 1)结果有名称空间和我不想要的额外的东西。 2)我不清楚使用哪种Saxon API将XQuery结果添加到现有文档中。因此,结果文档看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<dataOfBooks:DataOfBooks xmlns:dataOfBooks="DataOfBooks">
  <Id>ID123</Id>
  <books>
    <book>
      <name>aaa</name>
      <serialNo>99</serialNo>
    </book>
    <book>
      <name>ccc</name>
      <serialNo>77</serialNo>
    </book>
  </books>
</dataOfBooks:DataOfBooks>

还有一个问题 - 我尝试使用dynamicContext和treeinfo类,因为我虽然使用treeinfo API可能更优,但没有运气。如果您认为使用TreeInfo API是有效的,我真的很感谢我的要求的代码示例。非常感谢您的帮助。

提前感谢您的时间和兴趣。

2 个答案:

答案 0 :(得分:1)

您的XQuery代码产生不需要的命名空间这一事实是因为您的查询错误,但除非您向我们展示代码,否则我们无法告诉您错误。

输出中的result:sequence表示你已经设法要求输出&#34;包裹&#34;格式,这表明某种滥用撒克逊API。同样,如果没有看到您的代码,我们无法准确地告诉您您做错了什么。

要对现有文档进行小的更改,保持其他文档不变,我通常会推荐XSLT而不是XQuery。在XSLT 3.0中,您可以使用以下样式表按名​​称对书籍进行排序:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0">

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="books">
  <xsl:copy>
    <xsl:perform-sort select="book">
      <xsl:sort select="name"/>
    </xsl:perform-sort>
  </xsl:copy>
</xsl:template>

</xsl:transform>

在XQuery和XSLT中,查询/转换的结果都是一个新文档,您可以使用它来代替原始文档。如果要对现有文档进行原位更新,可以使用XQuery Update执行此操作;但Saxon不支持针对DOM4J格式的文档进行XQuery更新。

Saxon允许您将查询或转换的结果捕获为DOM4J文档,并且您可以使用DOM4J API将此文档(或者更确切地说,其最外层元素)移植回原始DOM4J文档。

<强>后来

您现在已经提供了代码(您应该将其作为原始问题的编辑提供,而不是作为答案)。

我猜你的DOMWriter是该名称的DOM4J类,它与DOM4J的大部分内容相似。但我认为它是将DOM4J树复制到DOM树,你绝对不想这样做。如果你真的想要复制树以方便Saxon,你应该将它复制到Saxon树,但对于这个用例,最好将它保留为DOM4J形式。使用

DocumentBuilder builder = processor.newDocumentBuilder();
XdmNode inDoc = builder.wrap(dom4jdoc);

当您运行查询时,生成的XdmValue现在将是一系列XdmNode对象,每个对象都是DOM4J Element节点的包装器。这些元素节点仍然附加到原始DOM4J树,并且它们仍然具有其原始名称空间。无需将结果序列化为词汇XML。

您可以通过编写

将结果复制到List值
List<Element> sortedNodes = new ArrayList<Element>();
for (XdmItem item : result) {
   sortedNodes.add(((Element)((XdmNode)item).getExternalNode()));
}

然后(如果我正确阅读了DOM4J文档),您可以用

替换包含books元素的内容
Element books = (Element)sortedNodes.get(0).getParent();
List booksContent = books.elements();
booksContent.clear();
booksContent.addAll(sortedBooks);

答案 1 :(得分:0)

谢谢迈克尔!

我修改了我的代码。新代码如下。我无法弄清楚用排序记录更新现有文档的方法。感谢帮助。修改后的代码如下:

 `          String expression = String.format(EXPRESSION, elementsToSort, sortExpression);//for $p in //books/book order by $p /serialNo descending return $p

        org.w3c.dom.Document doc = new DOMWriter().write(dom4jDoc);

        Processor processor = new Processor(false);
        XQueryCompiler compiler = processor.newXQueryCompiler();
        XQueryExecutable exp = compiler.compile(expression);
        //DocumentBuilder builder = processor.newDocumentBuilder();
        //XdmNode inDoc = builder.wrap(doc);

        XQueryEvaluator evaluator = exp.load();
        evaluator.setSource(new DOMSource(doc));
        //evaluator.setContextItem(inDoc);
        XdmValue result = evaluator.evaluate();

        for (XdmSequenceIterator iter = result.iterator(); iter.hasNext();) {
            XdmItem item = iter.next();
            System.out.println(" sorted record: " + item.getStringValue());

            //TODO: How to update the original document with these sorted records?

        }

        //This shows the sorted records as XML BUT has the uneccessary namesspace xmlns:data="dataOfBooks" for each record.
        StringWriter sw = new StringWriter();
        Serializer out = processor.newSerializer(sw);
        out.setOutputProperty(Serializer.Property.METHOD, "xml");
        out.setOutputProperty(Serializer.Property.ESCAPE_URI_ATTRIBUTES, "true");
        out.setOutputWriter(sw); 
        processor.writeXdmValue(result, out);
        System.out.println("sorted records XML with uneccessary namesspace issue: " + sw.toString());`