java - JAXB 强制命名空间 URI - 为什么它期望某些命名空间,即使它没有定义?

标签 java xml xml-parsing namespaces jaxb

当我试图解开 XML 文档时,我感到很困惑:

意外元素(uri:“http://www.xxx/xsd/ems/batchreq”,本地:“batchParams”)。预期元素为 <{}msgCollection>,<{}batchParams>]

元素不应该带有命名空间 - 它在 xml 中没有,也不在 java 类中,但似乎在解析它时,它会获得命名空间 uri - 更神秘的是,具有命名空间的元素似乎并不期望它。

为什么?

将命名空间添加到 @XmlElement 会有所帮助,但似乎必须为每个元素定义它 - 这是 Not Acceptable 解决方案。为什么子元素不能继承命名空间?

根类是:

@XmlRootElement(name = "batch", namespace = "http://www.xxx/xsd/ems/batchreq")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "batch", namespace = "http://www.xxx/xsd/ems/batchreq", propOrder = { "batchParams", "msgCollection" })
public class Batch {

    @XmlAttribute(required = true)
    private String batchName;


    @XmlElement(name = "batchParams", required = true)
    private BatchParams batchParams;

    @XmlElement(name = "msgCollection", required = true)
    private Msgs msgCollection;
...

违规成员(member)类别是:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "batchParams", namespace = "http://www.xxx/xsd/ems/batchreq", propOrder = { "msgCount", "dateCreated" })
public class BatchParams {

    @XmlElement()
    private Long msgCount;

    @XmlElement()
    private Date dateCreated;

    public Long getMsgCount() {
...

Xml 文档是:

<?xml version="1.0" encoding="UTF-8"?>
<batch xmlns="http://www.xxx/xsd/ems/batchreq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xxx/xsd/ems/batchreq ./ems_msg_batchreq.xsd" batchName="d" msgType="ems_sendemsg_batchreq" sourceSystem="1">
  <batchParams>
    <msgCount>1</msgCount>
    <dateCreated>2014-12-03T12:00:00</dateCreated>
  </batchParams>
  <msgCollection xmlns="http://www.xxx/xsd/ems/req">
    <msg msgType="ems_sendemsg_msg" sourceSystem="1" dataSourceSystem="1">
...
    </msg>
  </msgCollection>
</batch>

最佳答案

Element should not come with namespace - it does not have in in xml, nor in java class, yet it seems that when it is parsed, it gets namespace uri - and for bigger mystery, elements that have namespace do not seem to expect it.

问题中的 XML 声明 http://www.xxx/xsd/ems/batchreq 作为默认命名空间。这意味着 XML 中未分配给不同命名空间的每个元素都将成为该命名空间的一部分。

<?xml version="1.0" encoding="UTF-8"?>
<batch xmlns="http://www.xxx/xsd/ems/batchreq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xxx/xsd/ems/batchreq ./ems_msg_batchreq.xsd" batchName="d" msgType="ems_sendemsg_batchreq" sourceSystem="1">
  <batchParams>
    <msgCount>1</msgCount>
    <dateCreated>2014-12-03T12:00:00</dateCreated>
  </batchParams>
  <msgCollection xmlns="http://www.xxx/xsd/ems/req">
    <msg msgType="ems_sendemsg_msg" sourceSystem="1" dataSourceSystem="1">
...
    </msg>
  </msgCollection>
</batch>
<小时/>

Adding namespace to @XmlElement helps, but then it seems that it would have to be defined for every single element - that is unacceptable solution.

您可以使用包级别 @XmlSchema 注释来映射默认命名空间限定。这是一个名为 package-info.java 的源文件,其中仅包含如下所示的内容。您需要更改包名称以匹配您的域模型。

@XmlSchema(
    namespace = "http://www.xxx/xsd/ems/batchreq",
    elementFormDefault = XmlNsForm.QUALIFIED)
package example;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
<小时/>

Why is namespace not inherited by child elements?

JAXB 中的命名空间规范确实会被继承,只是不是以您尝试的方式继承。

  1. 包级别 @XmlSchema 注释提供了一种指定默认命名空间的方法,该命名空间应由与该包中的类和属性相对应的所有元素继承。
  2. 类型级别@XmlType 注释提供了一种指定此类上所有属性继承的命名空间的方法。这会覆盖 @XmlSchema 注释上指定的命名空间信息。
  3. 最后,可以在 @XmlRootElement@XmlElement 注释(以及其他一些注释)上指定命名空间。此处指定的命名空间仅适用于该元素。

了解更多信息

我在我的博客上写了有关此用例的更多信息:

关于java - JAXB 强制命名空间 URI - 为什么它期望某些命名空间,即使它没有定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28188325/

相关文章:

java - 使用 WebDriver 自动化非英语网站

java - 从 map 存储条目是否安全?它会导致内存泄漏吗?

java - 从 Android 发送 HttpPost 请求,从 PHP 读取 Post

java - android数据库连接如何?

java - 如何处理基于模板的解析器中的冗余标记名称

java - SWT 源代码编辑器小部件

javascript - 使用 Javascript 获取 XML 文件中节点内的节点

python - 如何使用 Python 按条件查找和删除 XML 文件(带有 namespace )中的元素

php - 如何使用 PHP 解析此 XML 字符串

ios - 在 UITableView 中滚动时图像变得困惑