XML - 資料交換管理/多對多關係
| 上一章 | 下一章 |
| ← 一對一關係 | 遞迴關係 → |
學習目標
|
簡介
[edit | edit source]在前面的章節中,您學習瞭如何使用 XML 根據一對一和一對多關係來構建和格式化資料。由於 XML 提供了使用分層父子關係對資料建模的方法,因此一對一和一對多關係在 XML 中相對容易表示。然而,這種分層父子結構難以用於對多對多關係進行建模,多對多關係是許多情況下實體之間常見的關聯關係。
在本章中,我們將探討幾種用於在 XML 中對多對多關係進行建模的方法的優缺點;這些方法在克服在將這種關係應用於 XML 時出現的難題方面做出了折衷。具體來說,我們將看到如何使用兩種不同的方法“消除”和“ID/IDREF”對多對多關係進行建模的示例。此外,在 XML 樣式表中,我們將學習如何實現 key 功能來顯示使用“ID/IDREF”方法建模的資料。
問題:多對多關係
[edit | edit source]在 XML 中,父子關係最常用於表示關聯關係。這可以很容易地應用於一對一或一對多關係。XML 不直接支援多對多關係;父子關係將無法正常工作,因為每個元素只能有一個父元素。為了解決這個問題,有幾種可能的解決方案。
解決方案:多對多關係
[edit | edit source]消除
[edit | edit source]建立消除多對多關係需求的 XML 文件
透過限制傳遞的資訊範圍,您可以避免多對多關係的需求。與其嘗試讓一個 XML 文件包含所有資訊,不如將資訊分開,其中一個文件僅描述參與多對多關係的實體之一。以我們的 tourGuide 關係為例,一種方法是為每個酒店建立單獨的 XML 文件。與 amenity 的關係最終將變成一對多關係。此方法更適合將資料交換範圍限制為資料集子集的情況。但是,在使用此方法進行範圍更廣的資料交換時,您可能會多次重複資料,尤其是如果存在許多屬性時。為了避免這種冗餘,請使用 ID/IDREF 方法。
ID/IDREF
[edit | edit source]使用唯一識別符號表示多對多關係
雖然這不是處理此問題的最友好的方法,但一種解決多對多關係的方法是建立鍵,這些鍵將唯一標識每個實體。為此,必須在 XML 架構中指定具有 ID 或 IDREF 屬性型別的元素。要使用資料建模類比,ID 類似於主鍵,而 IDREF 類似於外部索引鍵。
多對多關係資料模型
[edit | edit source]此關係表示為“一家酒店可以擁有許多便利設施,而一個便利設施可以在許多酒店存在”。
如您所見,為了表示多對多關係,添加了兩個實體。中間實體對於資料模型來說是必要的,因為它儲存了關於酒店和便利設施之間關係的資料。使用我們的旅遊指南示例,添加了“Amenity”來表示酒店可以擁有的可能便利設施列表。
以下示例說明了在 XML 中表示多對多關係的方法。
消除:示例解決方案
[edit | edit source]在此示例中,多對多關係已轉換為一對多關係。
XML 架構
[edit | edit source]圖示 2:“消除”方法的 XML 架構
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Document : amenity1.xsd
Created on : February 4, 2006
Author : Dr. Rick Watson
-->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
<xsd:element name="hotelGuide">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="hotel" type="hotelDetails" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="emailAddressType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\w+\W*\w*@{1}\w+\W*\w+.\w+.*\w*"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="hotelDetails">
<xsd:sequence>
<xsd:element name="hotelPicture"/>
<xsd:element name="hotelName" type="xsd:string"/>
<xsd:element name="streetAddress" type="xsd:string"/>
<xsd:element name="postalCode" type="xsd:string" minOccurs="0"/>
<xsd:element name="telephoneNumber" type="xsd:string"/>
<xsd:element name="emailAddress" type="emailAddressType" minOccurs="0"/>
<xsd:element name="websiteURL" type="xsd:anyURI" minOccurs="0"/>
<xsd:element name="hotelRating" type="xsd:integer" default="0"/>
<xsd:element name="lowerPrice" type="xsd:positiveInteger"/>
<xsd:element name="upperPrice" type="xsd:positiveInteger"/>
<xsd:element name="amenity" type="amenityValue" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="amenityValue">
<xsd:sequence>
<xsd:element name="amenityType" type="xsd:string"/>
<xsd:element name="amenityOpenHour" type="xsd:time"/>
<xsd:element name="amenityCloseHour" type="xsd:time"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
XML 文件
[edit | edit source]圖示 3:“消除”方法的 XML 文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : amenity1.xml
Created on : February 4, 2006
Author : Dr. Rick Watson
-->
<hotelGuide xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="amenity1.xsd">
<hotel>
<hotelPicture/>
<hotelName>Narembeen Hotel</hotelName>
<streetAddress>Churchill Street</streetAddress>
<telephoneNumber>+61 (08) 9064 7272</telephoneNumber>
<emailAddress>narempub@oz.com.au</emailAddress>
<hotelRating>1</hotelRating>
<lowerPrice>50</lowerPrice>
<upperPrice>100</upperPrice>
<amenity>
<amenityType>Restaurant</amenityType>
<amenityOpenHour>06:00:00</amenityOpenHour>
<amenityCloseHour>22:00:00 </amenityCloseHour>
</amenity>
<amenity>
<amenityType>Pool</amenityType>
<amenityOpenHour>06:00:00</amenityOpenHour>
<amenityCloseHour>18:00:00 </amenityCloseHour>
</amenity>
<amenity>
<amenityType>Complimentary Breakfast</amenityType>
<amenityOpenHour>07:00:00</amenityOpenHour>
<amenityCloseHour>10:00:00 </amenityCloseHour>
</amenity>
</hotel>
<hotel>
<hotelPicture/>
<hotelName>Narembeen Caravan Park</hotelName>
<streetAddress>Currall Street</streetAddress>
<telephoneNumber>+61 (08) 9064 7308</telephoneNumber>
<emailAddress>naremcaravan@oz.com.au</emailAddress>
<hotelRating>1</hotelRating>
<lowerPrice>20</lowerPrice>
<upperPrice>30</upperPrice>
<amenity>
<amenityType>Pool</amenityType>
<amenityOpenHour>10:00:00</amenityOpenHour>
<amenityCloseHour>22:00:00 </amenityCloseHour>
</amenity>
</hotel>
</hotelGuide>
ID/IDREF:示例解決方案
[edit | edit source]為了避免冗餘,我們建立了一個單獨的元素“amenity”,它與“hotel”一起包含在架構的頂部。請記住,資料型別 ID 和 IDREF 分別與主鍵和外部索引鍵同義。對於每個外部索引鍵(IDREF),都必須有一個匹配的主鍵(ID)。請注意,IDREF 資料型別必須是字母數字字串。
以下示例說明了 ID/IDREF 方法。請注意,便利設施泳池的 ID 定義為“k1”,每個擁有泳池作為便利設施的酒店都使用 IDREF 引用“k1”。如果 IDREF 與任何 ID 不匹配,則文件將無法驗證。
XML 架構
[edit | edit source]圖示 4:“ID/IDREF”方法的 XML 架構
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Document : amenity2.xsd
Created on : February 4, 2006
Author : Dr. Rick Watson
-->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
<xsd:element name="hotelGuide">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="hotel" type="hotelDetails" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="amenity" type="amenityList" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="emailAddressType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\w+\W*\w*@{1}\w+\W*\w+.\w+.*\w*"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="hotelDetails">
<xsd:sequence>
<xsd:element name="hotelPicture"/>
<xsd:element name="hotelName" type="xsd:string"/>
<xsd:element name="streetAddress" type="xsd:string"/>
<xsd:element name="postalCode" type="xsd:string" minOccurs="0"/>
<xsd:element name="telephoneNumber" type="xsd:string"/>
<xsd:element name="emailAddress" type="emailAddressType" minOccurs="0"/>
<xsd:element name="websiteURL" type="xsd:anyURI" minOccurs="0"/>
<xsd:element name="hotelRating" type="xsd:integer" default="0"/>
<xsd:element name="lowerPrice" type="xsd:positiveInteger"/>
<xsd:element name="upperPrice" type="xsd:positiveInteger"/>
<xsd:element name="amenities" type="amenityDesc" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="amenityDesc">
<xsd:sequence>
<xsd:element name="amenityIDREF" type="xsd:IDREF"/>
<xsd:element name="amenityOpenHour" type="xsd:time"/>
<xsd:element name="amenityCloseHour" type="xsd:time"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="amenityList">
<xsd:sequence>
<xsd:element name="amenityID" type="xsd:ID"/>
<xsd:element name="amenityType" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
XML 文件
[edit | edit source]圖示 5:“ID/IDREF”方法的 XML 文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : amenity2.xml
Created on : February 4, 2006
Author : Dr. Rick Watson
-->
<?xml-stylesheet href="amenity2.xsl" type="text/xsl" media="screen"?>
<hotelGuide xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="amenity2.xsd">
<hotel>
<hotelPicture/>
<hotelName>Narembeen Hotel</hotelName>
<streetAddress>Churchill Street</streetAddress>
<telephoneNumber>+61 (08) 9064 7272</telephoneNumber>
<emailAddress>narempub@oz.com.au</emailAddress>
<hotelRating>1</hotelRating>
<lowerPrice>50</lowerPrice>
<upperPrice>100</upperPrice>
<amenities>
<amenityIDREF>k2</amenityIDREF>
<amenityOpenHour>06:00:00</amenityOpenHour>
<amenityCloseHour>22:00:00 </amenityCloseHour>
</amenities>
<amenities>
<amenityIDREF>k1</amenityIDREF>
<amenityOpenHour>06:00:00</amenityOpenHour>
<amenityCloseHour>18:00:00 </amenityCloseHour>
</amenities>
<amenities>
<amenityIDREF>k5</amenityIDREF>
<amenityOpenHour>07:00:00</amenityOpenHour>
<amenityCloseHour>10:00:00 </amenityCloseHour>
</amenities>
</hotel>
<hotel>
<hotelPicture/>
<hotelName>Narembeen Caravan Park</hotelName>
<streetAddress>Currall Street</streetAddress>
<telephoneNumber>+61 (08) 9064 7308</telephoneNumber>
<emailAddress>naremcaravan@oz.com.au</emailAddress>
<hotelRating>1</hotelRating>
<lowerPrice>20</lowerPrice>
<upperPrice>30</upperPrice>
<amenities>
<amenityIDREF>k1</amenityIDREF>
<amenityOpenHour>10:00:00</amenityOpenHour>
<amenityCloseHour>22:00:00 </amenityCloseHour>
</amenities>
</hotel>
<amenity>
<amenityID>k1</amenityID>
<amenityType>Pool</amenityType>
</amenity>
<amenity>
<amenityID>k2</amenityID>
<amenityType>Restaurant</amenityType>
</amenity>
<amenity>
<amenityID>k3</amenityID>
<amenityType>Fitness room</amenityType>
</amenity>
<amenity>
<amenityID>k4</amenityID>
<amenityType>Complimentary breakfast</amenityType>
</amenity>
<amenity>
<amenityID>k5</amenityID>
<amenityType>in-room data port</amenityType>
</amenity>
<amenity>
<amenityID>k6</amenityID>
<amenityType>Water slide</amenityType>
</amenity>
</hotelGuide>
為了使用 ID/IDREF 方法為多對多關係設定 XML 樣式表,應該使用關鍵功能。在樣式表中,<xsl:key> 元素指定索引,該索引用於從 XML 文件中返回節點集。
一個鍵包含以下部分:
1. 包含鍵的節點
2. 鍵的名稱
3. 鍵的值
以下 XML 樣式表說明了如何使用鍵功能來呈現以多對多關係結構化的內容。
圖 6: 用於“ID/IDREF” 方法的 XML 樣式表
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : amenity2.xsl
Created on : February 4, 2006
Author : Dr. Rick Watson
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="amList" match="amenity" use="amenityID"/>
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title>Hotel Guide</title>
</head>
<body>
<h2>Hotels</h2>
<xsl:apply-templates select="hotelGuide"/>
</body>
</html>
</xsl:template>
<xsl:template match="hotelGuide">
<xsl:for-each select="hotel">
<xsl:value-of select="hotelName"/>
<br/>
<xsl:for-each select="amenities">
<xsl:value-of select="key('amList',amenityIDREF)/amenityType"/>
<xsl:text> </xsl:text>
<xsl:value-of select="amenityOpenHour"/> -
<xsl:value-of select="amenityCloseHour"/>
<BR/>
</xsl:for-each>
<br/>
<br/>
</xsl:for-each>
<br/>
</xsl:template>
</xsl:stylesheet>
|
Expedia.de 是 Expedia.com 的德國子公司,Expedia.com 是一家總部位於美國華盛頓州貝爾維尤的網路旅遊代理商。它透過其網站和電話為客戶提供機票預訂、租車、度假套餐以及各種其他景點和服務。其網站每月吸引超過 7000 萬遊客。目前,Expedia.com 擁有 4600 名員工,為美國、加拿大、英國、法國、德國、義大利和澳大利亞的客戶提供服務。 出於營銷目的,Expedia.de 建立了一個聯盟營銷計劃。聯盟營銷是一種在不承擔任何財務風險的情況下接觸潛在客戶的方式,這種方式針對的是想要做廣告的公司(商家)。商家為網站所有者(稱為聯盟夥伴)提供了指向商家頁面的推薦機會,並提供基於佣金的貨幣獎勵作為激勵。在 Expedia.de 的案例中,每當使用者從其網站預訂 Expedia.de 的行程時,聯盟夥伴就會獲得佣金。因此,聯盟夥伴可以專注於銷售,而商家則負責處理交易。 為了簡化聯盟夥伴的業務 - 當然也為了使該計劃更具吸引力 - Expedia.de 為其夥伴提供了一項名為 xmlAdEd 的服務。xmlAdEd 是一項提供當前產品資訊的基於 XML 的服務。使用該服務的聯盟夥伴可以透過 HTTP 請求以 XML 格式獲取超過 800 萬種旅行產品的請求。資料每天更新多次。在 HTTP 請求中,您可以設定某些引數,例如地點、價格、機場程式碼等。 在這種情況下使用 XML 為聯盟夥伴帶來了許多優勢: 透過為其聯盟夥伴提供 XML 格式的產品資訊,Expedia.de 不僅簡化了其合作伙伴的業務,而且確保客戶能夠獲得其服務的一致、最新的資訊。 |
| 在 XML 中描述多對多關係時,設計師可以使用幾種解決方案。在選擇如何表示多對多關係時,設計師不僅要考慮以最有效的方式表示資訊,還要考慮文件的目標受眾以及文件的使用方式。 |
http://www-128.ibm.com/developerworks/xml/library/x-xdm2m.html
