第 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 的属性” 描述 任何
元素的属性。
属性 | 描述 |
---|---|
| 指定可用于实例化 XML 文档中的元素的命名空间。有效值为:
|
|
指定元素中可显示的最大次数。默认值为: |
|
指定父元素中可显示元素实例的最小次数。默认值为: |
| 指定用于实例化任何元素的元素的方式。有效值为:
|
例 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 类:
- 它将根据已知运行时的元素列表检查 XML 元素的元素标签。如果找到匹配项,则运行时会将 XML 数据整理到元素的正确 JAXB 类中。
-
它将检查 XML 元素的
xsi:type
属性。如果找到匹配项,则运行时会将 XML 元素派生到该类型的正确的 JAXB 类中。 -
如果无法找到匹配项,它将 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
注解在运行时映射中添加类型。