java读取xml单个标签
W3C XML Schema由于其强大的数据键入和定义功能而已成为许多业务应用程序的核心。 但是数据模型并不总是静态的。 模式通常需要一些方法来允许随着时间的推移进行扩展,以适应新的信息和元素类型。 有几种方法可以根据需要扩展架构以包括新元素:本文介绍的六种策略提供了扩展单命名空间架构的技术。 使用多个名称空间扩展正在处理的数据需要其自己的文章。
注意:本文仅关注W3C XML Schema 1.0版。 W3C XML Schema工作组即将完成1.1版,但尚未批准,并且可能会更改。 此处的示例均基于当前规范。
通用元素
代码列表是随时间变化的数据的一个很好的例子。 代码列表是具有特定含义的唯一代码值的列表,例如产品描述符,常用术语以及国家或城市列表。 这些值通常存储在数据库行中,您可以随时间添加这些行,并用于在应用程序窗口中填充选择。
清单1中的简单颜色代码清单说明了如何在出现新数据选择时扩展模式。 它定义了一个简单的代码列表,其元素类型为color
,其中包含四个可能的元素,其中前三个被赋予了已知的颜色名称。 该组中的最后一个元素有时称为通用元素 ,旨在允许将任何值插入到name
属性中,从而使您可以随着时间的推移向列表中添加新颜色。 如果要在应用程序完成和部署后几个月选择新的颜色,则可以指定一种新的颜色(也许是紫色),并使用other
属性为name="purple"
元素。 验证后,允许<other>
元素,并且无需更改所需的架构即可继续工作。
清单1.定义可扩展颜色代码列表元素的示例模式
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="color">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="red" type="xs:string"/>
<xs:element name="blue" type="xs:string"/>
<xs:element name="green" type="xs:string"/>
<xs:element name="other">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
清单2是与使用通用元素扩展的与此模式相关联的有效数据的样本。
清单2.与颜色代码列表模式关联的有效数据实例
<color xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="color.xsd">
<red/>
<green/>
<other name="purple">cc00cc</other><!-- Extension data -->
<other name="orange">ee9944</other><!-- Extension data -->
</color>
如您所见,该架构并未定义名称为Purple或Orange的元素,但是由于使用了扩展技术,这些名称已包含在数据实例中并被解析为有效。 该技术在存在静态列表但不断添加新项目的地方有效。 数据的创建可能会稍微复杂一些,但是维护架构和相关应用程序会大大简化。 当然,此数据可以管理属性而不是元素中的所有颜色信息。
当数据实例中出现通用<other>
元素时,处理该数据需要进行特殊处理。 XQuery或XSLT样式表中的XPath语句可能会测试预定义的元素之一,并显示已知的颜色。 两种语言都可以选择已知元素名称之一进行相应处理,或者可以选择<other>
元素并读取name=
的属性值和颜色值的元素内容(在此以CSS样式值表示)相应的颜色)。
模块化架构组装
您可能出于多种原因将模式模块化,但是本节重点介绍使用模块化来扩展它们。 简而言之,创建几个模式模块并将其包含在基本模式中是扩展基本模式的一种形式。 清单3中的示例使用模式构造<xs:include>
引入模式模块。
清单3.使用xs:include引入模式模块
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Reference to External Module containing USaddress definition -->
<xs:include schemaLocation="USaddress.xsd"/>
<!-- Element containing USaddress element from included module -->
<xs:complexType name="contact">
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element ref="USaddress"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
清单4.包含的模式模块
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="USaddress">
<xs:complexType>
<xs:sequence>
<xs:element name="street1" type="xs:string" minOccurs="0"/>
<xs:element name="street2" type="xs:string" minOccurs="0"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="state" type="xs:string"/>
<xs:element name="zip" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
组合后的结果模式允许清单5中的数据实例成功验证。
清单5.使用包含的模式验证的数据实例
<contact>
<name>Dale Waldt</name>
<USaddress>
<city>New York</city>
<state>NY</state>
</USaddress>
</contact>
请注意,解析的架构将包含原始架构和所包含架构的所有声明。 因为清单5中的示例仅使用一个名称空间,所以元素和属性名称在组合的解析形式中必须是唯一的。 另外,发生规则在解析形式中必须一致。
尽管添加模块是扩展模式的一种形式,但是构建一组动态组装的模块以为不同环境和应用程序创建灵活模式的潜力是优化开发和维护工作的强大概念。 您可以创建预定义一致声明的库,以供开发人员在整个企业中有选择地使用。 即使这样,也要特别小心以防止发生命名冲突和其他错误,尤其是在单个名称空间中。
抽象元素和替代组
W3C XML Schema允许将通常出现在相同位置的一类元素类型视为类型定义中的一组等效元素。 例如,您可能有几种类型的命名对象(即人,地方,事物)在文本中显示为嵌入式元素,包括人,城市,住宿,餐馆和博物馆。 您可以为文本<p>
元素定义一个内容模型,如清单6所示 ,该文本模型被定义为带有名为<b>
, <i>
和<inline>
子元素的混合内容。粗体,斜体和其他内联元素。
清单6.定义属于替代组成员的元素
<!-- Paragraph Element Type Definition with Abstract Element -->
<xs:element name="p">
<xs:complexType>
<xs:choice maxOccurs="unbounded" mixed="true">
<xs:element name="b" type="xs:string"/>
<xs:element name="i" type="xs:string"/>
<xs:element ref="inline"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="inline" type="xs:string"/>
<!-- Substitution Element Types -->
<xs:element name="person" type="xs:string" substitutionGroup="inline"/>
<xs:element name="hotel" type="xs:string" substitutionGroup="inline"/>
<xs:element name="city" type="xs:string" substitutionGroup="inline"/>
<xs:element name="url" type="xs:string" substitutionGroup="inline"/>
<xs:element name="email" type="xs:string" substitutionGroup="inline"/>
<xs:element name="phone" type="xs:string" substitutionGroup="inline"/>
请注意,在清单6中 , <inline>
元素是在属性substitutionGroup="inline"
引用的,该属性位于紧随<inline>
的元素声明中。 这意味着作为替换组成员且具有另一个元素名称的所有元素都可以放置在允许该元素的任何位置(或抽象元素可以实现此目的)。 在此示例中,允许替换组元素类型<person>
, <phone>
等在<inline>
元素所在的任何位置(在这种情况下,是段落中的文本)。 清单7中的数据实例对此模式及其替换组扩展有效。 (您也可以将此技术与引用抽象元素的替换一起使用。)
清单7.使用替换组元素的有效数据实例
<p>This is a <b>paragraph</b> with several inline elements. This sentence mentions
<city>Chicago</city>, <person>Mayor Daly</person> and
<hotel>The Drake Hotel</hotel> which are named entities that have specific
markup applied to them. </p>
还要注意,所有受影响的元素必须全局声明,而不是在其他类型定义的上下文中声明。 替换组元素可以按任何顺序出现,因为它们位于具有maxOccurs="unbounded"
的可重复选择组中。
随着时间的流逝,新用途可能需要添加内联元素。 使该示例可扩展的原因在于,模式开发人员仅需添加一个新元素声明即可表明它是替代组的成员。 当然,可以在单独存储并包含在主模式中的模式模块中管理作为替换组成员的元素声明块。 这样做可以简化向替换组添加新元素声明的过程,甚至可以从应用程序界面进行管理和生成,这与管理和扩展代码列表的方式几乎相同。
扩展到现有类型
W3C XML Schema允许您扩展现有的类型定义以添加其他子元素,并向数据模型的结构添加其他元素。 您可以将扩展应用于元素或属性的类型。 给定清单8中的示例类型定义,您可以定义包含人员姓名信息的元素的内容。
清单8.一个简单的类型定义
<xs:complexType name="nameType">
<xs:sequence>
<xs:element name="fname" type="xs:string"/>
<xs:element name="lname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
该定义将解析下面的实例为有效(假设元素<name>
是使用nameType
类型定义的):
<name><fname>Dale</fname><lname>Waldt</lname></name>
您可以使用清单9中的示例为名为nameType
的复杂类型提供其他子元素。 在此示例中,您可以看到名为extendedNameType
的新complexType
显示该扩展nameType
应用于基本类型nameType
(如上定义)。 一旦扩展,基本类型将继承其自身定义之外的新扩展类型的属性。 在这种情况下,您打算将子元素<gen>
到上面定义的nameType
元素,该元素已经具有<fname>
和<lname>
元素作为子元素。
清单9.使用xs:extension将元素添加到nameType
<xs:complexType name="extendedNameType">
<xs:extension base="nameType">
<xs:sequence>
<xs:element name="gen" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexType>
<xs:element name="para" ref="extendedNameType"/>
清单9中定义的<para>
元素使用extendedNameType
,它已被定义为包括其基本类型nameType
和扩展元素<gen>
所有子元素。 这将使以下实例得以正确验证:
<para><fname>Dale</fname><lname>Waldt</lname><gen>Jr.</gen></para>
为了更好地了解验证期间实际发生的情况, 清单10中的示例表示了验证程序解析扩展时的结果(这是处理模式时的视图,有时称为Post Schema Validation Infoset,或PSVI)。 。 如您所见,解析并没有简单地在原始<xs:sequence>
元素中lname
的最后一个元素声明之后立即插入<gen>
元素的新声明。 相反,它在原始元素之后立即添加了一个新的<xs:sequence>
元素,从而产生了一系列序列,并将其封装在其他<xs:sequence>
元素中以保留顺序。 实际上,扩展只能应用于合成器<xs:sequence>
,而不能应用于其对应的<xs:choice>
或<xs:all>
。 (实际上,您可以扩展<xs:choice>
合成器,但是最终会插入<xs:sequence>
元素。)
清单10.解析的扩展类型
<xs:complexType name="ExtendedNameType">
<xs:sequence>
<xs:sequence>
<xs:element name="fname" type="xs:string"/>
<xs:element name="lname" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="gen" type="xs:string"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
同样, 清单10中的代码允许以下实例进行验证:
<name><fname>Dale</fname><lname>Waldt</lname><gen>Jr</gen></name>
您还可以在扩展类型时添加属性,如清单11所示 ,扩展了ParaType
复杂类型定义以为label=
添加属性。
清单11.使用xs:extension将属性添加到命名类型
<xs:complexType name="ParaType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="label" type="xs:string"
use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="para" type="ParaType"/>
清单11中的扩展示例允许以下文本实例成功验证:
<para label="abc">Paragraph string text.</para>
重新定义现有类型
一个模式中定义的类型可以在另一个模式模块中重用和重新定义。 如果您继承模式,但想要对定义进行一些修改以使其在您的环境中更好地工作,则此行为很方便。 假设您得到了一个行业标准的架构,该架构为yearType
简单类型定义了simpleType
,如清单12所示 。
清单12.定义一个简单类型为yearType的模式模块
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:simpleType name="yearType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:element name="year" type="yearType"/>
</xsd:schema>
清单12中的yearType
严格定义为<xs:string>
,对于您的本地环境而言可能不够严格。 也许在更广阔的世界中,您会发现年份包含两位或四位数,甚至可能包含撇号,例如'09。 但是在您的内部环境中,您可能希望强制年份始终为四个数字,以便尽可能明确。 考虑一个单独的模式模块,该模块通过schemaLocation=
属性调用原始模式,并使用清单13中的代码对其进行重新定义。
清单13.重新定义名为yearType的简单类型的Schema模块
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:redefine schemaLocation="prod1.xsd">
<xsd:simpleType name="yearType">
<xsd:restriction base="yearType">
<xsd:length value="4"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:redefine>
<xsd:element name="fullYear" type="yearType"/>
</xsd:schema>
因为yearType
已经被重新定义,所以仍使用相同的名称来引用它,但是当将它应用于<fullYear>
元素时,它将确保fullYear
始终包含四个数字。
请注意,重新定义要求新旧定义与其原始数据类型具有相同的原始类型。 在清单13的示例中,它定义为xs:string
。
通配符
W3C XML Schema允许您使用通配符或可以包含几乎任何其他元素或属性(无论是否声明)的元素声明一些元素。 通配符ANY
类型是一个占位符,其内容可能会或可能不会根据架构进行验证。 通过将processContents
属性设置为以下级别之一来控制验证:
- 跳过:不验证内容。
- 松懈:仅在找到相应的声明时验证。
- 严格:根据当前架构进行验证。
分别使用<xs:any>
或<xs:anyAttribute>
元素定义元素或属性的通配符。 清单14中的示例显示了一个名为<HTMLExample>
的元素,该元素具有通配符,将在其中声明从属元素或属性。 换句话说, <HTMLExample>
元素可以包含任何其他元素,只要它们具有格式正确的标记即可。 您可以添加XHTML Schema并允许元素对其进行解析,然后将processContent
级别设置为lax
以检查其是否为有效HTML标记。 但是此示例不会打扰检查通配符元素,因此将其设置为skip
。
清单14.使用xs:any和xs:anyAttribute通配符的元素声明
<xs:element name="HTMLExample">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
</xs:sequence>
<xs:anyAttribute processContents="skip"/>
</xs:complexType>
</xs:element>
具体来说, 清单14中的示例显示了元素声明,该元素声明包含一个复杂的类型,该类型包含一个序列。 该序列包含<any>
元素,它是通配符占位符,指示任何元素标记都可以出现在此位置。 它还包含一个<xs:anyAttribute>
声明,该声明允许将任何格式正确的属性添加到元素标记中。 因为应该跳过此元素内容的处理,所以不会在开始标记和结束标记之间的内容上执行任何模式验证。 因此,整个元素可以使用任何元素或属性名称包含任何格式正确的标记。 这样,您可以在此元素内添加来自其他文档模型的内容,从而扩展了文档中允许的所有元素类型(即使在特定位置)。 在此示例中, 清单15中的数据实例是有效的。
清单15.有效HTMLExample数据实例
<HTMLExample href="http://www.w3.org">
<tr>
<th align="left">Table Head</th>
</tr>
</HTMLExample>
在清单15的示例中,通常根据模式验证元素类型<HTMLExample>
,但是将跳过该元素的内容,表行和表头HTML元素。
如果希望要求验证或使用松散验证(如果可以找到架构),则在使用通配符时要当心。 必须使资源(例如要验证的替代方案)对处理器可用。 命名空间必须正确管理。 此外,将通配符与可选元素或可重复元素结合使用可能会导致歧义和不确定性条件。 最简单地将通配符与processContents="skip"
将使您避免大部分此类复杂性。
结论
从本文的示例中可以看到,W3C XML Schema语言的设计人员在创建标准时就牢记了可扩展性。 请注意每种扩展类型的规则,以使其起作用。 这些功能强大的技术尽管仅在单个名称空间中起作用,但可以提供极大的灵活性,尤其是在使用分布式和多种环境中使用的架构时。
展望未来,请密切关注W3C XML Schema工作组正在制定的新兴XML Schema 1.1版标准。 它对通配符和其他构造进行了一些有趣的更改,可能会影响此处显示的示例。
翻译自: https://www.ibm.com/developerworks/xml/library/x-xtendschema/index.html
java读取xml单个标签