【问题标题】:Is it valid to specify xsi:type for an local complexType?为本地 complexType 指定 xsi:type 是否有效?
【发布时间】:2014-04-25 04:21:19
【问题描述】:

自从将服务器升级到 jaxb 2 后,我们遇到了 xsi:type 问题。当服务器运行 jaxb 1 时,有问题的 xml 客户端请求解析正常,但自从升级到 jaxb 2 后,我们看到了一个错误行:

Error::cvc-elt.4.2: Cannot resolve 'er-request' to a type definition for element 'er-request'

客户端将xsi:type 指定为xml 标记中的属性,但我认为它无效,因为所讨论的复杂类型没有这样的名称。

<?xml version="1.0" encoding="UTF-8"?>
<er-request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="100007" xsi:type="er-request">
    <payload>
     <!--some content-->
    </payload>
</er-request>

这是xsd:

<xs:element name="er-request">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="payload" type="payloadType" minOccurs="0"/>
        </xs:sequence>
        <xs:attribute name="id" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:int"/>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>

<xs:complexType name="payloadType">
    <xs:sequence>
        <xs:any processContents="skip" minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

如您所见,complexType 中没有name 属性。我们可以通过添加它来解决该错误,但随后我们会看到一个验证错误,因为显然是本地 complexType 上的 name 属性:

Attribute 'name' cannot appear in element 'complexType'

我认为这在 jaxb1 中起作用的原因是它没有 jaxb 2 严格。

所以问题是:

  1. 客户端 xml 是否有效?
  2. 我们可以尝试使 jaxb2 更宽松的其他解决方法吗?

【问题讨论】:

    标签: xml xml-parsing jaxb xsd jaxb2


    【解决方案1】:

    您的 XML 文档有效吗?

    不,正如您所说,xsi:type 属性的值与您的 XML 架构中的命名复杂类型不对应。

    这有关系吗?

    JAXB 实现的目标是非常容错。使用最新 JDK 1.7 安装或 EclipseLink JAXB (MOXy) 中的默认 JAXB impl,我无法让您的示例失败:

    ErRequest

    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name="er-request")
    public class ErRequest {
    
    }
    

    演示

    import javax.xml.bind.*;
    import javax.xml.transform.stream.StreamSource;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(ErRequest.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            StreamSource xml = new StreamSource("src/forum22497112/input.xml");
            ErRequest erRequest = (ErRequest) unmarshaller.unmarshal(xml);
    
        }
    
    }
    

    错误来自哪里

    您遇到的错误似乎是架构验证错误:

    错误::cvc-elt.4.2: 无法将“er-request”解析为类型定义 对于元素'er-request'

    您是否要求 JAXB 对输入执行模式验证?默认情况下,JAXB 不这样做。由于您的文档无效,您必须修复它或注册一个错误侦听器以忽略它。

    【讨论】:

    • 感谢 Blaise 的又一个冗长而有用的答案。我完全忽略了这样一个事实,即我们确实在针对模式验证请求。关闭验证解决了问题(或至少解决了它)。
    【解决方案2】:

    您需要将匿名复杂类型提升为全局(命名)类型:

    <xs:element name="er-request" type="er-request"/>
    
    <xs:complexType name="er-request">
            <xs:sequence>
                <xs:element name="payload" type="payloadType" minOccurs="0"/>
            </xs:sequence>
            <xs:attribute name="id" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:int"/>
                </xs:simpleType>
            </xs:attribute>
    </xs:complexType>
    

    或者,只需删除 xsi:type 属性。它在这里没有做任何有用的事情,因为元素名称足以识别所需的类型。

    【讨论】:

    • 嗨迈克尔,感谢您的建议。我曾想过,但问题是对架构的任何更改都会受到反对,即使在这种情况下我们没有进行任何真正的更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2011-06-03
    • 2011-10-07
    • 1970-01-01
    • 2019-06-09
    相关资源
    最近更新 更多