使用Saxon修改XPath 2.0结果树

时间:2015-03-04 05:18:58

标签: saxon xpath-2.0

我想

  1. 添加/删除/更新元素/属性/值到“subTree”
  2. 能够将更新的“targetDoc”保存回“目标”文件位置。
  3. 确定哪个树模型最适合此xpath +树修改过程。
  4. 我以为我应该能以某种方式获得MutableNodeInfo对象,但我不知道如何做到这一点。我尝试使用processor.setConfigurationProperty(FeatureKeys.TREE_MODEL,Builder.LINKED_TREE);但这仍然给我一个TinyElementImpl的基础节点。我需要xpath 2.0以避免必须输入默认命名空间,这就是为什么我使用saxon s9api而不是Java的默认DOM模型。如果可能的话,我还想避免使用xslt / xquery,因为这些树修改是动态完成的,这使得xslt / xquery在我的情况下更加复杂。

    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();
        }
    
    }
    

2 个答案:

答案 0 :(得分:1)

我认为你可以向Saxon提供一个DOM节点并针对它运行XPath但是在这种情况下你不使用Saxon本机树的文档构建器,你使用javax.xml.parsers.DocumentBuilder构建一个DOM,一旦你有您可以使用Saxon wrap的{​​{1}}方法将其提供给Saxon的W3C DOM节点。以下是从Saxon 9.6 resources file

中的文件S9APIExamples.java中获取的示例代码
DocumentBuilder

还有一些示例展示了如何将Saxon与JDOM和其他可变树实现一起使用,但我认为您需要Saxon PE或EE直接支持这些实现。

答案 1 :(得分:0)

Saxon中的MutableNodeInfo接口是专为满足XQuery Update的需求而设计的,我建议不要试图直接从Java中使用它;在处理XQuery Update以外的方法调用时,实现不可能是健壮的。

事实上,Saxon NodeInfo接口被设计为XPath的目标,而不是用户编写的Java代码。因此,我建议使用第三方树模型;我最喜欢的是JDOM2和XOM。这两种方法都允许您使用Saxon使用XPath 2.0导航来混合直接Java导航和更新。