XML - 数据交换管理/递归关系
上一章 | 下一章 |
← 多对多关系 | 数据模式 → |
学习目标
|
递归关系是一个有趣且比你在前几章中看到的更复杂的概念。当实体之间存在关系时,就会出现递归关系。例如,一对多递归关系发生在员工是其他员工的经理时。员工实体与其自身相关,并且一个员工(经理)与许多其他员工(向经理汇报的人)之间存在一对多关系。由于这些关系的性质更复杂,因此我们需要稍微复杂一些的方法来将它们映射到模式并以样式表的方式显示它们。
继续以导游模型为例,我们将开发一个模式,该模式显示举办过奥运会的城市以及上一个举办城市。由于上一个举办城市是另一个城市,并且只有一个城市可以成为上一个举办城市,因此这是一对一递归关系。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="cities">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="city" type="cityType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="cityType">
<xsd:sequence>
<xsd:element name="cityID" type="xsd:ID"/>
<xsd:element name="cityName" type="xsd:string"/>
<xsd:element name="cityCountry" type="xsd:string"/>
<xsd:element name="cityPop" type="xsd:integer"/>
<xsd:element name="cityHostYr" type="xsd:integer"/>
<xsd:element name="cityPreviousHost" type="xsd:IDREF" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
图 1:举办城市实体的 XML 架构
<?xml version="1.0" encoding="UTF-8"?>
<cities xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='host.xsd'>
<city>
<cityID>c1</cityID>
<cityName>Atlanta</cityName>
<cityCountry>USA</cityCountry>
<cityPop>4000000</cityPop>
<cityHostYr>1996</cityHostYr>
</city>
<city>
<cityID>c2</cityID>
<cityName>Sydney</cityName>
<cityCountry>Australia</cityCountry>
<cityPop>4000000</cityPop>
<cityHostYr>2000</cityHostYr>
<cityPreviousHost>c1</cityPreviousHost>
</city>
<city>
<cityID>c3</cityID>
<cityName>Athens</cityName>
<cityCountry>Greece</cityCountry>
<cityPop>3500000</cityPop>
<cityHostYr>2004</cityHostYr>
<cityPreviousHost>c2</cityPreviousHost>
</city>
</cities>
图 2:奥运会举办城市的 XML 文档
假设一个运动队分为多个小队,每个小队都有一名队长。团队中的每个人都是球员,无论他们是否是小队队长。由于小队队长也是球员,因此这种情况符合递归关系的定义——小队队长也是球员,并且与其他球员之间存在一对多关系。这是一种一对多递归关系,因为一名队长手下有多名球员。请查看下面的示例了解如何对这种关系进行建模。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
<xsd:element name="team">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="player" type="playerType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="playerType">
<xsd:sequence>
<xsd:element name="playerID" type="xsd:ID"/>
<xsd:element name="playerName" type="xsd:string"/>
<xsd:element name="playerCap" type="playerC" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="playerC">
<xsd:sequence>
<xsd:element name="memberOf" type="xsd:IDREF"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
图 3:团队实体的 XML 架构
<?xml version="1.0" encoding="UTF-8"?>
<team xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='Recursive1toMSchema.xsd'>
<player>
<playerID>c1</playerID>
<playerName>Tommy Jones</playerName>
<playerCap>
<memberof>c3</memberof>
</playerCap>
</player>
<player>
<playerID>c2</playerID>
<playerName>Eddie Thomas</playerName>
<playerCap>
<memberof>c3</memberof>
</playerCap>
</player>
<player>
<playerID>c3</playerID>
<playerName>Sean McCombs</playerName>
</player>
<player>
<playerID>c4</playerID>
<playerName>Patrick O’Shea</playerName>
<playerCap>
<memberof>c3</memberof>
</playerCap>
</player>
</team>
图 4:团队实体的 XML 文档
对于大多数一对多递归关系来说,更自然的方法是使用 XML 的层次结构来直接表示层次结构。请考虑地点
<?xml version="1.0" encoding="UTF-8"?>
<location type="country">
<name>USA</name>
<sub-locations>
<location type="state">
<name>Ohio</name>
<sub-locations>
<location type="city"><name>Akron</name></location>
<location type="city"><name>Columbus</name></location>
</sub-location>
</location>
</sub-locations>
</location>
你认为你已经了解递归关系了吗?好吧,你的技能库中还有第三种也是最后一种关系需要添加——多对多递归关系。多对多递归关系的一个常见示例是,一个项目可以由许多与其自身数据类型相同的项目组成,并且这些子项目中的每一个可能属于另一个与自身数据类型相同的父项目。听起来很困惑?让我们以一个产品为例,它可以包含单个项目或多个项目(即,包装产品)。下面的示例描述了可以打包在一起形成新产品的旅游产品。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
<xsd:element name="products">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="product" type="prodType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="prodType">
<xsd:sequence>
<xsd:element name="prodID" type="xsd:ID"/>
<xsd:element name="prodName" type="xsd:string"/>
<xsd:element name="prodCost" type="xsd:decimal" minOccurs="0"/>
<xsd:element name="prodPrice" type="xsd:decimal"/>
<xsd:element name="components" type="componentsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="componentsType">
<xsd:sequence>
<xsd:element name="component" type="xsd:IDREF"/>
<xsd:element name="componentqty" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
图 5:产品实体的 XML 架构
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="product.xsl"?>
<products xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="product.xsd">
<product>
<prodID>p1000</prodID>
<prodName>Animal photography kit</prodName>
<prodPrice>725</prodPrice>
<components>
<component>p101</component>
<componentqty>1</componentqty>
</components>
</product>
<product>
<prodID>p101</prodID>
<prodName>Camera case</prodName>
<prodCost>150</prodCost>
<prodPrice>300</prodPrice>
</product>
</products>
图 6:产品实体的 XML 文档
当子元素在父子类型数据关系中与父元素具有相同类型的数据时,这表明存在递归关系。xsd:ID 和 xsd:IDREF 元素可以在模式中使用,以在 XML 文档中创建主键-外键值。
外部链接