级别: 初级 Russell Butek (butek@us.ibm.com), 软件工程师, IBM Richard Scheuerle (scheu@us.ibm.com), 软件工程师, IBM
2004 年 1 月 01 日 一些程序依赖于零数组(null array)和空数组(empty array)之间的差别。在 XML Schema 中数组的表示却没有这样的差别。您能不能采取办法来克服 XML 的这个特征不利的方面呢?本文将给您展示一种解决这种问题的方法。
当使用 Web
服务时,常常总是假设所有在编程语言中能够做的事情也同样能够在 XML
做到。在很多情况下并不是这样的。这里介绍的技巧用于处理其中的一个情况:一个为“零”的数组和一个没有元素的数组之间的差别。
XML 数组
大部分编程语言,比如说 Java 语言,都有数组的概念:相似元素的有序集合。同样,XML
也有相似元素的有序集合: 一个具有
maxOccurs 属性且该属性值大于1的 XML schema 元素。所以,有理由说 Java 语言中的相似元素的有序集合能够很好地映射到 XML 中的相似元素的有序集合。
清单 1 中定义了一个
complexType ,其中就包含有这样一个 XML schema “数组”。
清单 1. 包含一个“数组”的 complexType
<complexType name="bean">
<sequence>
<element name="name" type="xsd:string"/>
<element name="array" minOccurs="0" maxOccurs="unbounded"
nillable="true" type="xsd:int"/>
</sequence>
</complexType>
|
问题
严格来说,这个 XML “数组”并不是一个数组。它是一个有
出现约束的元素,也就是说这个元素被定义出现特定的次数,在这里可以是
0 次或更多次。听起来这非常像一个数组,对于大多数的意图和目的,它也确实是一个数组。但是这一映射并不完美。您应该意识到这个缺点,这样以来您就不会被它们意外地诱入陷阱。
依据 JAX-RPC 的映射规则,
清单 1 中的
complexType 将变成
清单 2中的 Java bean (实际上,这个 bean 将有 getters 和 setters,但是在这个讨论中我们将简化它)。
清单 2. 包含一个数组的 bean。
public class Bean {
public java.lang.String name;
public java.lang.Integer[] array;
}
|
(注意:这个
Bean 的数组变量是一个
java.lang.Integer 数组, 不是一个
int 数组。XML schema 中的数组元素是可为“零”的(nillable)。Java
int 不能为“零”(null)。
java.lang.Integer 可以为“零”(null)。所以在这一映射中我们使用
java.lang.Integer 。)
表 1显示许多 Java Bean 的实例和相应的 XML 实例之间映射的例子。第一行是 Java 表示;第二行是相应的 XML 表示。
请注意
表 1
中有一个显而易见的事实——它是这个技巧的主题——就是一个 Java 数组的空(empty)实例和一个 Java 数组的“零”(null)实例都映射到相同的 XML 实例。如果您正依赖两者的差别,这确实不是一个好办法。
很容易落入的一个陷阱就是猜测在表的第二列中用 XML 表示在
Bean 中的“零”(null)数组。但是,正如我们希望的,在表中已经显示,它真正表示的是含有单一元素的数组,元素的值为“零”(null),而不是一个“零”(null)数组。
存在解决这个问题的方法吗?
当然!已经知道的事情是在大多数编程语言中的数组其实是由两部分组成的:数组的内容和数组本身——如果您喜欢,也可以这样形容,内容和包在外面的包装。一个 XML “数组”只是元素的列表,而没有“包装”。
所以,解决的方法很简单:为数组创建一个“包装”,正如
清单 3所示。
清单 3.
包含包装的数组的 bean
<complexType name="arrayWrapper">
<sequence>
<element name="el" nillable="true" maxOccurs=
"unbounded" minOccurs="0" type="xsd:int"/>
</sequence>
</complexType>
<complexType name="bean">
<sequence>
<element name="name" type="xsd:string"/>
<element name="array" nillable="true" type="
tns:arrayWrapper"/>
</sequence>
</complexType>
|
表 2 是对于这个 XML
Schema 的数组示例表格。
正如您可以看到的,
arrayWrapper complexType
的空实例和零实例彼此之间是有差别的。
 |
包装的数组的映射
WebSphere Application Server 6.0
将认可这种特殊的包装的数组模式。代替生成额外的 Java
Bean,它将简单地生成您在
清单 2
中所看到的 Bean。Microsoft 的 .NET
也认可这种包装的数组模式,并且生成友好的 C# 代码。
|
|
这一解决方法并不是“百宝丹”。首先,它比用简单的
minOccurs /
maxOccurs
表示数组要复杂得多。其次,这个 XML Schema
不是包含一个数组的简单 Bean,其实它看起来像这样一个 Bean,在这个
Bean 中包含一个含有数组的 Bean;如果您用自己喜欢的 JAX-RPC
WSDL-to-Java 工具将这个 XML Schema 映射到 Java
编程,就很可能以它结束。只有在标准组织适当地认可和映射这个包装的数组模式之后,您才能应用这一解决方法(如果您确实需要区别零数组和空数组的话)。
总结
XML “数组”并不是编程语言意义上的真正的数组。XML
不区分零数组(null array)和空数组(empty array)。您可以遵循一种 XML
Schema
模式来等价地获取这种差别,但是这个模式没有得到标准组织很好的认可,仅当绝对必须时才应该使用。
参考资料
作者简介  | |  | Russell Butek 是 IBM WebSphere Web 服务引擎的开发人员之一。他也是 JAX-RPC Java Specification Request(JSR)专家组的 IBM 代表。他从事 Apache 的 AXIS SOAP 引擎的实现方面的研究,推动了 AXIS 1.0 遵循 JAX-RPC 1.0。以前,他是 IBM CORBA ORB 的开发人员和 许多 OMG 特别工作组的 IBM 代表:包括可移植拦截器特别工作组(他是这个特别工作组的主席)、核心特别工作组以及互操作性特别工作组。您可以通过
butek@us.ibm.com与 Russell 联系。
|
 | |  | Richard Scheuerle 是 IBM WebSphere Web 服务引擎的开发人员之一。他从事 Apache 的 AXIS SOAP 引擎的实现方面的研究。Richard 有 10 年的编译器/语言设计的开发经验。现在他侧重于 Web 服务引擎性能和 API 设计。Richard 也从事 CORBA 工具和芯片确认软件的开发。您可以通过
scheu@us.ibm.com与 Richard 联系。
|
对本文的评价
|