我们假设了一个需要你作出这样决定的环境,并据此给出了一个良好的设计模式来帮助你解决问题。
设想一下,假如你不能完全肯定将要向一个确定的元素中输入什么类型的数据,或者说你根本不知道将要输入的数据是什么数据,当然你也就不知道其结构是如何的。这对于你将要设计的文档结构来说确实是个大麻烦。
下面让我们来看一个例子,假设你的XML文档中有一个叫Item的元素。输入这个元素的数据来自各种不同的来源(比如经过不同的分割或者合并后的数据)。如果数据来源是经过分割后的,我们可以预见到其格式并能用简单方式描述出来;而如果来源是合并后的数据,那其格式也许可以用松散文本方式描述。问题是,你怎么能同时对这两种情况进行描述呢?
一个解决方案是使用混合内容元素。所谓混合内容元素并不是什么高深的概念,它其实就是将结构化的和非结构化的数据同时装入同一个元素。
混合内容元素是定义在文档类型定义(DTD)中的。列表A是一个简单的DTD,说明了如何定义一个混合内容元素。
Listing A: mixedcontent.dtd
<!ELEMENT Order (Item+)>
<!ELEMENT Item (#PCDATA | Description)*>
<!ELEMENT Description (#PCDATA)>
上面这段代码是经过精简的。它显示了一个指令元素可以包含一个或多个项目元素。每个项目元素又可以包含文本数据或者一个子描述(Description)元素。由于混合内容元素的这个性质,你可以不用再过度关注有什么样的结构化数据出现了。
下面我们来看一个更具体的问题并讨论一下这个问题的解决方案。假设我们有一个订单,就像上面所示的,既包含了未经加工的数据又包含了结构化的XML内容。列表B显示了这个XML文档的实际样子。
Listing B: order.xml
<Order>
<Item>
<SKU>KKU8123</SKU>
<Name>Super Widget</Name>
<Description>A super widget device</Description>
<PricePer>13.50</PricePer>
</Item>
<Item>
8234556:Hyper Flange, .95
</Item>
<Item>
Small metallic device for assisting in flotalating.
<Name>Metallic Flotalator</Name>
<PricePer>.50</PricePer>
</Item>
</Order>
这个订单包含多个项目,并且项目数据来自不同的系统,数据格式也不一样。好在我们可以用混合内容元素来描述每个项目,而不必破坏XML文档。
列表C是上面DTD的扩展,每个项目中除了未经处理的数据外,还加入了SKU、Name、Description、PricePer。这个DTD会很好的解释列表B中的XML文档。
Listing C: mixedcontent2.dtd
<!ELEMENT Order (Item+)>
<!ELEMENT Item (#PCDATA | SKU | Name | Description | PricePer)*>
<!ELEMENT SKU (#PCDATA)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Description (#PCDATA)>
<!ELEMENT PricePer (#PCDATA)>
当处理XML数据时,你一定要认真决定如何组织数据才是最优的方案。解决复杂数据格式问题的一个方案是使用混合内容元素,它可以同时包含未经处理的原始数据和结构化的子元素。
本文作者Brian Schaffner是富士通咨询公司的副主任。他为富士通的技术咨询公司提供架构、设计和开发支持。