第 36 章 使用 Wild 卡类型


摘要

当架构作者希望防御元素或属性到定义的类型时,会存在实例。对于这些情况,XML Schema 为指定通配符位置拥有者提供了三种机制。它们都以保留其 XML Schema 功能的方式映射到 Java。

36.1. 使用 Any Elements

概述

XML Schema 任何 元素用于在复杂类型定义中创建通配符位置拥有者。当 XML 元素实例化为 XML Schema any 元素时,它可以是任何有效的 XML 元素。any 元素不对内容或实例化 XML 元素的名称施加任何限制。

例如,给定 例 36.1 “使用 Any Element 定义的 XML Schema 类型” 中定义的复杂类型,您可以实例化 例 36.2 “带有任何元素的 XML 文档” 中显示的任一 XML 元素。

例 36.1. 使用 Any Element 定义的 XML Schema 类型

<element name="FlyBoy">
  <complexType>
    <sequence>
      <any />
      <element name="rank" type="xsd:int" />
    </sequence>
  </complexType>
</element>

例 36.2. 带有任何元素的 XML 文档

<FlyBoy>
  <learJet>CL-215</learJet>
  <rank>2</rank>
</element>
<FlyBoy>
  <viper>Mark II</viper>
  <rank>1</rank>
</element>

XML Schema 任何 元素都映射到 Java 对象对象或 Java org.w3c.dom.Element 对象。

在 XML Schema 中指定

定义复杂类型和选择复杂类型时,可以使用任何 元素。在大多数情况下,任何 元素都是空的元素。不过,它可以 将注解 元素作为子项。

表 36.1 “XML Schema Any Element 的属性” 描述 任何 元素的属性。

表 36.1. XML Schema Any Element 的属性
属性描述

namespace

指定可用于实例化 XML 文档中的元素的命名空间。有效值为:

##any
指定可以使用任何命名空间中的元素。这是默认值。
##other
指定父元素命名空间以外的任何命名空间中的元素
##local
必须使用没有命名空间的元素。
##targetNamespace
指定必须使用父元素命名空间中的元素。
空格分隔的 URI #\#local\#\#targetNamespace
指定可以使用列出的任何命名空间中的元素。

maxOccurs

指定元素中可显示的最大次数。默认值为:1。要指定元素的实例可以显示无限次数,您可以将 属性的值设置为 未绑定

minOccurs

指定父元素中可显示元素实例的最小次数。默认值为:1

processContents

指定用于实例化任何元素的元素的方式。有效值为:

strict
指定元素必须根据正确的模式进行验证。这是默认值。
lax
指定该元素是否应该根据正确的模式进行验证。如果无法验证,则不会抛出任何错误。
skip
指定不应验证这个元素。

例 36.3 “使用 Any 元素定义的复杂类型” 显示 使用任何 元素定义的复杂类型

例 36.3. 使用 Any 元素定义的复杂类型

<complexType name="surprisePackage">
  <sequence>
    <any processContents="lax" />
    <element name="to" type="xsd:string" />
    <element name="from" type="xsd:string" />
  </sequence>
</complexType>

映射到 Java

XML Schema 任何 元素都会导致创建名为 任何 的 Java 属性。属性关联了 getter 和 setter 方法。生成的属性的类型取决于元素的 processContents 属性的值。如果 将任何 元素的 processContents 属性设置为 skip,则该元素将映射到 org.w3c.dom.Element 对象。对于 processContents 属性的所有其他值,任何 元素都映射到 Java 对象对象。

生成的属性使用 @XmlAnyElement 注释进行解码。此注解具有一个可选 lax 属性,用于指示运行时在分离数据时要做什么。它的默认值是 false,它指示运行时自动将数据分到 org.w3c.dom.Element 对象。将 lax 设为 true 会指示运行时尝试将数据分到 JAXB 类型中。当任何 元素的 processContents 属性设置为 skip 时,lax 属性设为默认值。对于 processContents 属性的所有其他值,lax 设置为 true

例 36.4 “带有任何元素的 Java 类” 显示 例 36.3 “使用 Any 元素定义的复杂类型” 中定义的复杂类型如何映射到 Java 类。

例 36.4. 带有任何元素的 Java 类

public class SurprisePackage {

    @XmlAnyElement(lax = true) protected Object any;
    @XmlElement(required = true)
    protected String to;
    @XmlElement(required = true)
    protected String from;

    public Object getAny() { return any; }

    public void setAny(Object value) { this.any = value; }

    public String getTo() {
        return to;
    }

    public void setTo(String value) {
        this.to = value;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String value) {
        this.from = value;
    }

}

marshalling

如果任何 元素的 Java 属性将其 lax 设为 false,或者未指定属性,则运行时不会尝试将 XML 数据解析为 JAXB 对象。数据始终存储在 DOM Element 对象中。

如果任何 元素的 Java 属性将其 lax 设为 true,则运行时会尝试将 XML 数据分到适当的 JAXB 对象中。运行时尝试使用以下步骤识别正确的 JAXB 类:

  1. 它将根据已知运行时的元素列表检查 XML 元素的元素标签。如果找到匹配项,则运行时会将 XML 数据整理到元素的正确 JAXB 类中。
  2. 它将检查 XML 元素的 xsi:type 属性。如果找到匹配项,则运行时会将 XML 元素派生到该类型的正确的 JAXB 类中。
  3. 如果无法找到匹配项,它将 XML 数据整理到 DOM Element 对象中。

应用程序运行时通常知道从该架构生成的所有类型的信息。这包括合同 wsdl:types 元素中定义的类型,通过导入其他模式而将任何数据类型添加到合同中,以及添加到合同的任何类型。您还可以使用 第 32.4 节 “在 Runtime Marshaller 中添加类” 中描述的 @XmlSeeAlso 注解使运行时了解额外的类型。

unmarshalling

如果任何 元素的 Java 属性将其 lax 设为 false,或者未指定属性,则运行时将仅接受 DOM Element 对象。尝试使用任何其他类型的对象将导致 marshalling 错误。

如果任何 元素的 Java 属性将其 lax 设为 true,则运行时在 Java 数据类型和 XML Schema 结构之间使用其内部映射,以确定要写入到有线的 XML 结构。如果运行时知道类,并可将其映射到 XML Schema 结构,它会写入数据并插入 xsi:type 属性来识别元素所包含的数据类型。

如果运行时无法将 Java 对象映射到已知的 XML Schema 结构,它将抛出异常。您可以使用 第 32.4 节 “在 Runtime Marshaller 中添加类” 中描述的 @XmlSeeAlso 注解在运行时映射中添加类型。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.