第 36 章 使用通配符类型
摘要
当一个 schema 作者希望将绑定元素或属性映射到定义的类型时,会有一些实例。对于这些情况,XML 架构提供了三个用来指定通配符放置拥有者的机制。它们都以保留其 XML 架构功能的方式映射到 Java。
36.1. 使用 Any Elements
概述
XML 架构 任何
元素用于在复杂类型定义中创建通配符拥有者。为 XML 架构 任何
元素实例化 XML 元素时,可以是任何有效的 XML 元素。any
元素不会对内容或实例化 XML 元素的名称施加任何限制。
例如,如果 例 36.1 “XML 架构类型通过 Any Element 定义” 中定义的复杂类型,您可以实例化 例 36.2 “带有任何元素的 XML 文档” 中显示的任一 XML 元素。
例 36.1. XML 架构类型通过 Any Element 定义
<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 架构 任何
元素都映射到 Java 对象对象或 Java org.w3c.dom.Element
对象。
在 XML 架构中指定
在定义复杂类型和选择复杂类型时,可以使用任何
元素。在大多数情况下,任何
元素是一个空元素。不过,它可以取 注释
元素作为子项。
表 36.1 “XML 架构任何元素的属性” 描述 任何
元素的属性。
属性 | 描述 |
---|---|
| 指定可用于实例化 XML 文档中的元素的元素的命名空间。有效值为:
|
|
指定元素中可以显示元素的最大次数。默认值为: |
|
指定元素中可以出现元素的最小次数。默认值为: |
| 指定实例化任何元素的元素应当如何进行验证。有效值为:
|
例 36.3 “使用 Any Element 定义的复杂类型” 显示 使用任何
元素定义的复杂类型
例 36.3. 使用 Any Element 定义的复杂类型
<complexType name="surprisePackage"> <sequence> <any processContents="lax" /> <element name="to" type="xsd:string" /> <element name="from" type="xsd:string" /> </sequence> </complexType>
映射到 Java
XML 架构 任何
元素会导致创建名为 any
的 Java 属性。属性关联了 getter 和 setter 方法。生成的属性的类型取决于元素的 processContents
属性的值。如果 将任何
元素的 processContents
属性设置为 跳过,则该
元素将映射到 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 Element 定义的复杂类型” 中定义的复杂类型如何映射到 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 属性设为 false
,或者未指定属性,则运行时不会试图将 XML 数据解析为 JAXB 对象。数据始终存储在 DOM
Element
对象中。
如果任何
元素的 Java 属性设为 true
,则运行时会尝试将 XML 数据放入适当的 JAXB 对象。运行时尝试使用以下步骤识别正确的 JAXB 类:
- 它会根据运行时已知的元素列表检查 XML 元素的元素标签。如果找到匹配项,则运行时摘要会将 XML 数据放入该元素的正确 JAXB 类中。
-
它检查 XML 元素的
xsi:type
属性。如果找到匹配项,则运行时摘要将 XML 元素放入该类型的正确 JAXB 类中。 -
如果无法找到与 XML 数据匹配的匹配,则将 XML 数据放入 DOM
Element
对象。
通常,应用程序的运行时会知道从其合同中包含的架构生成的所有类型。其中包括合同的 wsdl:types
元素中定义的类型、通过包含添加到合同的任何数据类型,以及通过导入其他模式向合同添加的任何类型。您还可以使用 @XmlSeeAlso
注释使运行时了解额外类型,如 第 32.4 节 “在 Runtime Marshaller 中添加类” 所述。
unmarshalling
如果任何
元素的 Java 属性设为 false
,或者未指定属性,则运行时将仅接受 DOM Element
对象。尝试使用其他类型的对象将导致错误。
如果任何
元素的 Java 属性设为 true
,则运行时会在 Java 数据类型和 XML 架构结构之间使用其代表的 XML 结构,以确定写入线的 XML 结构。如果运行时知道类并可以映射到 XML 架构结构,它将写入数据并插入
xsi:type
属性来识别元素包含的数据类型。
如果运行时无法将 Java 对象映射到已知的 XML 架构结构,它将引发汇总异常。您可以使用 @XmlSeeAlso
注释(如 第 32.4 节 “在 Runtime Marshaller 中添加类” 中所述),向运行时添加类型。