【问题标题】:XMLUnit Diff testing XPath when XML doc contains namespaces当 XML 文档包含命名空间时,XMLUnit Diff 测试 XPath
【发布时间】:2017-03-15 08:55:58
【问题描述】:

我想比较两个 xml 文档

d1.xml

<?xml version="1.0" encoding="UTF-8"?>
<test:process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/Application2/FileRead1/BPELProcess1 xsd/BPELProcess1.xsd" xmlns:test="http://xmlns.oracle.com/Application2/FileRead1/BPELProcess1">
    <test:input1>RAVI1</test:input1>
   <test:input2>RAVI2</test:input2>
</test:process>

d2.xml

<?xml version="1.0" encoding="UTF-8"?>
<test:process xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/Application2/FileRead1/BPELProcess1 xsd/BPELProcess1.xsd" xmlns:test="http://xmlns.oracle.com/Application2/FileRead1/BPELProcess1">
    <test:input1>RAVI1</test:input1>
   <test:input2>RAVI2</test:input2>
</test:process>

使用以下代码编写了一个 java 代码来对这些 XML 文件进行比较

 public static void main(String[] args) throws Exception {
              
       String sourceXml = new String(readAllBytes(get("c:\\temp\\d1.xml")));
       String targetXml = new String(readAllBytes(get("c:\\temp\\d2.xml")));
       
    XPathEngine engine = new JAXPXPathEngine(); 
    
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
            
        Document sourceDoc = Convert.toDocument(Input.fromString(sourceXml).build(), dbf);
       
        Document targetDoc = Convert.toDocument(Input.fromString(targetXml).build(), dbf);
        
        Diff myDiff = DiffBuilder.compare(sourceDoc).withTest(targetDoc)
                    .checkForSimilar()
                                 .checkForIdentical()
                    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes))
                    .ignoreWhitespace() 
                    .withNamespaceContext(null)
                    .build();
   
        Iterator<Difference> iter = myDiff.getDifferences().iterator();
           int size = 0;
           while (iter.hasNext()) {
             
              Difference d1 =  iter.next();
               System.out.println(d1);
             
            System.out.println(d1.getComparison().getControlDetails().getXPath()  +" (SOURCE) -->  "+d1.getComparison().getControlDetails().getValue());
            System.out.println(d1.getComparison().getTestDetails().getXPath()  +" (TARGET) -->  "+d1.getComparison().getTestDetails().getValue());
              
               System.out.println();
               size++;
           }
    }
    

这是输出,我得到了

预期的文本值“RAVI2”但为“RAVI3” - 将 /process[1]/input2[1]/text()[1] 中的 RAVI2 与 /process[1]/input2[1]/text 中的 RAVI3 进行比较()[1](不同) /process[1]/input2[1]/text()[1] (SOURCE) --> RAVI2 /process[1]/input2[1]/text()[1] (目标) --> RAVI3

这里的 Xpath 不包含命名空间 /process[1]/input1[1]/text()[1] 我希望这是,

/test:process[1]/test:input1[1]/text()

在我的代码中,我尝试使用这个 Xpath,但它没有给出任何结果。如果 XML 不包含命名空间,那么这可以正常工作。

XPathEngine 引擎 = 新的 JAXPXPathEngine();

字符串值 = engine.evaluate(d1.getComparison().getTestDetails().getXPath(), Input.fromString(targetXml).build()); System.out.println("------------------ " +value);

【问题讨论】:

    标签: xpath xmlunit


    【解决方案1】:

    我在你的两个例子中都没有看到RAVI3

    无论如何,如果您想要带有命名空间前缀的 XPath,您必须指定包含所需映射的 NamespaceContext(实际上是从前缀到 uri 的 Map)。请参阅Javadocs of DiffBuilder

    【讨论】:

    • 我想获取任何随机的 xml 文件,所以我可能不知道 xml 文件使用的命名空间。有什么方法可以获取 xml 文件包含的所有命名空间。
    • 我不知道有什么比解析文档和检查每个 Node 的名称空间 URI 更简单的方法。请注意,您可以在文档中使用相同的前缀(在不同的上下文中)拥有多个 URI,也可以使用不同的前缀在相同的 URI 中使用 - 因此,简单地使用文档中使用的前缀通常不会起作用。这就是我决定让 XMLUnit 的用户明确指定映射的原因。如果 XMLUnit 创建代理 ns1ns2 ... 前缀,您将不知道如何与真正的命名空间 URI 匹配。
    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多