我是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是有效的,我真的很感谢我的要求的代码示例。非常感谢您的帮助。
提前感谢您的时间和兴趣。
答案 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());`