【问题标题】:How to call xpath deep-equal in java如何在java中调用xpath deep-equal
【发布时间】:2015-12-10 17:26:34
【问题描述】:

我正在尝试比较两个 (org.jdom2.Document) xml 文档并将它们插入到我的 xpath 表达式中。

String xpathExpression = "//[fn:deep-equal("+testDocument+","+ expectedDocument+")]";

这不会编译。正确的语法是什么?

另外,我希望这个表达式返回一个布尔值。我应该使用

List<Text> textValues = xpath.evaluate(testDocument);

得到结果?

【问题讨论】:

  • w3.org/TR/xquery-operators/#func-deep-equal 返回一个布尔值并将两个序列作为其参数。而deep-equals 是 XPath 2.0 或更高版本,您是否将 JDOM 与 XPath 2.0 实现一起使用?
  • 正确的语法是简单的“deep-equal($x, $y)”。您的语法是错误的,因为(a)您希望答案是布尔值,而不是满足布尔值的某些节点集的某个子集,并且(b)如果您确实想要一个谓词来过滤节点集,那么之前的事情谓词必须是有效的表达式,而“//”本身不是有效的表达式。
  • @Michael Kay 我试过 String xpathExpression = String.format("deep-equal(%s,%s)",testDocument,expectedDocument);两个文档都已填充。我得到一个 XPathSyntaxException: Caused by: class org.jaxen.saxpath.XPathSyntaxException: deep-equal([Document: No DOCTYPE declaration, Root is [Element: policy.model.com/]/>]],[Document: No DOCTYPE declaration, Root is [Element :policy.model.com/]/>]]):11:意外的 '['
  • Jim:你不能期望 document.toString() 的结果是你可以连接成 XPath 表达式的东西!无论如何,我认为 Jaxen 不支持 XPath 2.0。您需要使用 Saxon 或其他一些 XPath 2.0 引擎。你为什么不按照@MartinHonnen 的建议去做?
  • @Michael Kay 我只是先尝试​​你的建议。

标签: java xml xpath


【解决方案1】:

PE 和 EE 版本中的 Saxon 支持对 JDOM 节点执行 XPath 2.0 评估,因此您可以编写 XPath 表达式 deep-equal(., $doc2) 其中上下文节点是第一个文档,变量 doc2 绑定到第二个文档文件:

Processor proc = new Processor(true);
proc.getUnderlyingConfiguration().registerExternalObjectModel(JDOM2ObjectModel.getInstance());

DocumentBuilder db = proc.newDocumentBuilder();

Document doc1 = new Document(new Element("root", "This is a test"));
Document doc2 = doc1.clone();

XdmNode xdmDoc1 = db.wrap(doc1);
XdmNode xdmDoc2 = db.wrap(doc2);

XPathCompiler xpath = proc.newXPathCompiler();
xpath.declareVariable(new QName("doc2"));

XPathExecutable xx = xpath.compile("deep-equal(., $doc2)");

XPathSelector sel = xx.load();
sel.setContextItem(xdmDoc1);
sel.setVariable(new QName("doc2"), xdmDoc2);

XdmItem result = sel.evaluateSingle();

System.out.println(result.toString());

【讨论】:

    【解决方案2】:

    我找到了一种方法,将 xml 文件转换为字符串,然后使用 org.custommonkey.xmlunit 来区分字符串。

    pom

    <dependency>
        <groupId>xmlunit</groupId>
        <artifactId>xmlunit</artifactId>
        <version>1.6</version>
    </dependency
    

    测试

    ...
    String test = xmlToString(testXml);
    String expected = xmlToString(expectedXml);
    ...
    Diff xmlDiff = new Diff(expected, test);
    assertTrue(xmlDiff.similar());
    ...
    

    将 xml 转换为字符串

    private String xmlToString(File xml)
            throws FileNotFoundException, IOException {
        BufferedReader br = new BufferedReader(new FileReader(xml));
        String line;
        StringBuilder sb = new StringBuilder();
    
        while((line=br.readLine())!= null){
            sb.append(line.trim());
        }
        br.close();
        return sb.toString();
    }
    

    差异可以自定义

    XMLUnit.setIgnoreWhitespace(true);
    XMLUnit.setIgnoreComments(true);
    XMLUnit.setIgnoreAttributeOrder(true);
    
    Diff xmlDiff = new Diff(expected, test);
    xmlDiff.overrideDifferenceListener(new DifferenceListener() {
        @Override
        public int differenceFound(Difference diff) {
            System.err.println("called: " + diff);
            int diffResult = RETURN_ACCEPT_DIFFERENCE;
    
            //ignore a node difference
            if(diff.getControlNodeDetail().getNode().getParentNode().getNodeName().contains("myNodeName")){
                skippedComparison(diff.getControlNodeDetail().getNode().getParentNode(), diff.getTestNodeDetail().getNode().getParentNode());
                diffResult = RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            } 
    
            return diffResult;
        }
        @Override
        public void skippedComparison(Node arg0, Node arg1) {}
    });
    
    assertTrue(xmlDiff.similar());    
    

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 2010-12-30
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多