【问题标题】:MockHttpServletResponse : Checking xml contentMockHttpServletResponse : 检查 xml 内容
【发布时间】:2014-04-07 18:38:23
【问题描述】:

我正在使用MockMvc 测试控制器。这是响应的样子:

MockHttpServletResponse:
              Status = 200
       Error message = null
             Headers = {Content-Type=[text/xml]}
        Content type = text/xml
                Body = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:diagnosisCode xmlns:ns2="http://schemas.mycompany.co.za/health" effectiveStartDate="2014-03-05T00:00:00+02:00" effectiveEndDate="2014-03-05T23:59:59.999+02:00" diagnosisId="1"><diagnosisCodeId><codingSchemaCode>irrelevant schema</codingSchemaCode><diagnosisCode>irrelevant code</diagnosisCode></diagnosisCodeId></ns2:diagnosisCode>
       Forwarded URL = null
      Redirected URL = null
             Cookies = []

Body 行的精美印刷版:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:diagnosisCode xmlns:ns2="http://schemas.mycompany.co.za/health" effectiveStartDate="2014-03-05T00:00:00+02:00" effectiveEndDate="2014-03-05T23:59:59.999+02:00" diagnosisId="1">
    <diagnosisCodeId>
        <codingSchemaCode>irrelevant schema</codingSchemaCode>
        <diagnosisCode>irrelevant code</diagnosisCode>
    </diagnosisCodeId>
</ns2:diagnosisCode>

MockMvc 上的调用看起来像

mockMvc.perform(
        get("/diagnostic/diagnosisCodes/{schema}/{code}", IRRELEVANT_SCHEMA, IRRELEVANT_CODE).accept(MediaType.TEXT_XML))
        .andDo(print())
        .andExpect(content().contentType(MediaType.TEXT_XML))
        .andExpect(status().isOk())
        .andExpect(xpath("diagnosisCodeId/diagnosisCode").string(IRRELEVANT_CODE))
        .andExpect(xpath("diagnosisCodeId/codingSchemaCode").string(IRRELEVANT_SCHEMA));

我很确定我误解了我应该如何在这里使用 XPath,但是为什么这个断言会失败?我的期望应该是什么样的?

java.lang.AssertionError: XPath diagnosisCode expected:<irrelevant code> but was:<>

【问题讨论】:

  • 您能否将源 XML 添加到问题中以及您希望使用 XPath 选择什么?

标签: xpath xml-namespaces spring-mvc-test


【解决方案1】:

xpath 有一个重载,需要 Map&lt;String, String&gt; 的命名空间:

Map<String, String> ns = Map.of("ns2", "http://schemas.mycompany.co.za/health");
mockMvc.perform(get("/diagnostic/diagnosisCodes/{schema}/{code}", IRRELEVANT_SCHEMA, IRRELEVANT_CODE)
        .accept(MediaType.TEXT_XML))
        .andExpect(xpath("ns2:diagnosisCodeId/diagnosisCode", ns).string(IRRELEVANT_CODE))
        .andExpect(xpath("ns2:diagnosisCodeId/codingSchemaCode", ns).string(IRRELEVANT_SCHEMA));

【讨论】:

    【解决方案2】:

    我不完全确定 XPath 上下文是什么(或者它是否是文档节点),但我看到了两个可能的问题并且猜测两者都适用:

    • 您尝试匹配作为根元素的&lt; diagnosisCodeId/&gt; 元素。没有,但他们是&lt;diagnosisCode&gt; 的孩子。要么包含根节点的轴步骤(可能更好的方法),要么在查询前面使用descendant-or-self 轴步骤//

      /diagnosisCode/diagnosisCodeId/diagnosisCode
      //diagnosisCodeId/diagnosisCode
      
    • 文档使用命名空间(用于根元​​素)。除了上面描述的根元素问题之外,要么注册该命名空间(更好的解决方案,但我不知道如何在 spring MVC 中执行此操作)或使用以下解决方法忽略它:

      /*[local-name() = 'diagnosisCode']/diagnosisCodeId/diagnosisCode
      

      首先匹配所有子节点,然后限制为具有适当元素名称的子节点(忽略命名空间)。

      通过添加 XPath 2.0 支持(例如 by including Saxon as library),您还可以使用通配符命名空间匹配器:

      /*:diagnosisCode/diagnosisCodeId/diagnosisCode
      

      如果您将命名空间 URI http://schemas.mycompany.co.za/health 注册为 ns2,查询将如下所示

      /ns2:diagnosisCode/diagnosisCodeId/diagnosisCode
      

    【讨论】:

    • 还有一个更简单的/*[local-name() = 'diagnosisCode']/*[local-name() = 'diagnosisCodeId']/*[local-name() = 'diagnosisCode'] 公式,即/*:diagnosisCode/*:diagnosisCodeId/*:diagnosisCode
    • spring mvc 支持 XPath 2.0 吗? Following to this answer 似乎是这样,我将其添加到答案中。
    • @adamretter 不幸的是,这对我不起作用。
    • @JensErat 我现在一切正常。唯一的问题是命名空间前缀应该只在根元素上。请编辑您的答案。
    • 你说得对,我忽略了命名空间只在元素中使用,没有应用默认命名空间。下一次,最好也添加一些漂亮的 XML 打印版本,让事情变得更容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多