使用Saxon修改XPath 2.0结果树
我想使用Saxon修改XPath 2.0结果树,saxon,xpath-2.0,Saxon,Xpath 2.0,我想 向“子树”添加/删除/更新元素/属性/值 能够将更新后的“targetDoc”保存回“target”文件位置 确定哪个树模型最适合这个xpath+树修改过程 我想我应该能够以某种方式获得一个MutableNodeInfo对象,但我不知道如何做到这一点。我尝试使用processor.setConfigurationProperty(FeatureKeys.TREE\u MODEL,Builder.LINKED\u TREE);但这仍然为我提供了TinyElementImpl的一个底层节点。我
public static void main(String[] args) {
// XML File namesspace URIs
Hashtable<String, String> namespaceURIs = new Hashtable<>();
namespaceURIs.put("def", "http://www.cdisc.org/ns/def/v2.0");
namespaceURIs.put("xmlns", "http://www.cdisc.org/ns/odm/v1.3");
namespaceURIs.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
namespaceURIs.put("xlink", "http://www.w3.org/1999/xlink");
namespaceURIs.put("", "http://www.cdisc.org/ns/odm/v1.3");
// The source/target xml document
String target = "Path to file.xml";
// An xpath string
String xpath = "/ODM/Study/MetaDataVersion/ItemGroupDef[@OID/string()='IG.TA']";
Processor processor = new Processor(true);
// I thought this tells the processor to use something other than
// TinyTree
processor.setConfigurationProperty(FeatureKeys.TREE_MODEL,
Builder.LINKED_TREE);
DocumentBuilder builder = processor.newDocumentBuilder();
XPathCompiler xpathCompiler = processor.newXPathCompiler();
for (Entry<String, String> entry : namespaceURIs.entrySet()) {
xpathCompiler.declareNamespace(entry.getKey(), entry.getValue());
}
try {
XdmNode targetDoc = builder.build(Paths.get(target).toFile());
XPathSelector selector = xpathCompiler.compile(xpath).load();
selector.setContextItem(targetDoc);
XdmNode subTree = (XdmNode) selector.evaluateSingle();
// The following prints: class
// net.sf.saxon.tree.tiny.TinyElementImpl
System.out.println(subTree.getUnderlyingNode().getClass());
/*
* Here, is where I would like to modify subtree and save modified doc
*/
} catch (SaxonApiException e) {
e.printStackTrace();
}
}
publicstaticvoidmain(字符串[]args){
//XML文件名称空间URI
Hashtable namespaceURIs=新的Hashtable();
namespaceURIs.put(“def”http://www.cdisc.org/ns/def/v2.0");
namespaceURIs.put(“xmlns”http://www.cdisc.org/ns/odm/v1.3");
namespaceURIs.put(“xsi”http://www.w3.org/2001/XMLSchema-instance");
namespaceURIs.put(“xlink”http://www.w3.org/1999/xlink");
namespaceURIs.put(“,”http://www.cdisc.org/ns/odm/v1.3");
//源/目标xml文档
String target=“file.xml的路径”;
//xpath字符串
字符串xpath=“/ODM/Study/MetaDataVersion/ItemGroupDef[@OID/String()='IG.TA']”;
处理器=新处理器(真);
//我想这会告诉处理器使用其他东西,而不是
//锡树
processor.setConfigurationProperty(FeatureKeys.TREE_模型,
链接树);
DocumentBuilder=processor.newDocumentBuilder();
XPathCompiler XPathCompiler=processor.newXPathCompiler();
for(条目:namespaceURIs.entrySet()){
declareNamespace(entry.getKey(),entry.getValue());
}
试一试{
XdmNode targetDoc=builder.build(path.get(target.toFile());
XPathSelector=xpathCompiler.compile(xpath.load();
选择器.setContextItem(targetDoc);
XdmNode子树=(XdmNode)选择器.evaluateSingle();
//以下打印:类
//net.sf.saxon.tree.tiny.TinyElementImpl
System.out.println(subTree.getUnderlyingNode().getClass());
/*
*在这里,我想修改子树并保存修改后的文档
*/
}捕获(萨克森例外){
e、 printStackTrace();
}
}
我认为您可以向Saxon提供一个DOM节点并对其运行XPath,但在这种情况下,您不需要为Saxon的原生树使用文档生成器,您可以使用javax.xml.parsers.DocumentBuilder
构建一个DOM,一旦有了W3CDOM节点,就可以使用SaxonDocumentBuilder的wrap
方法将其提供给Saxon。以下是从中的文件S9APIExamples.java中获取的示例代码:
还有一些示例展示了如何将Saxon与JDOM和其他可变树实现结合使用,但我认为您需要Saxon PE或EE来直接支持这些实现。Saxon中的可变节点信息接口是专为满足XQuery更新的需要而设计的,我建议不要尝试直接从Java使用它;当处理XQuery Update发出的方法调用以外的方法调用时,该实现可能不太健壮
事实上,Saxon NodeInfo接口通常被设计为XPath的目标,而不是用户编写的Java代码。因此,我建议使用第三方树模型;我最喜欢的是JDOM2和XOM。这两种方法都允许您混合使用直接Java导航和使用Saxon的XPath 2.0导航进行更新。谢谢。这很好用。甚至在使用默认JavaDOM时,XPath2.0的某些元素也可以使用这种方法。在试图提出解决方案时,我不知何故忽略了DocumentBuilder.wrap()的使用。另外,感谢@Michael Kay澄清了MutableNodeInfo和建议树模型的使用。
// Build the DOM document
File file = new File("data/books.xml");
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
dfactory.setNamespaceAware(true);
javax.xml.parsers.DocumentBuilder docBuilder;
try {
docBuilder = dfactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new SaxonApiException(e);
}
Document doc;
try {
doc = docBuilder.parse(new InputSource(file.toURI().toString()));
} catch (SAXException e) {
throw new SaxonApiException(e);
} catch (IOException e) {
throw new SaxonApiException(e);
}
// Compile the XPath Expression
Processor proc = new Processor(false);
DocumentBuilder db = proc.newDocumentBuilder();
XdmNode xdmDoc = db.wrap(doc);
XPathCompiler xpath = proc.newXPathCompiler();
XPathExecutable xx = xpath.compile("//ITEM/TITLE");
// Run the XPath Expression
XPathSelector selector = xx.load();
selector.setContextItem(xdmDoc);
for (XdmItem item : selector) {
XdmNode node = (XdmNode) item;
org.w3c.dom.Node element = (org.w3c.dom.Node) node.getExternalNode();
System.out.println(element.getTextContent());
}