XML/一对多关系

< XML

XML > 一对多关系


学习目标:

编辑

完成本章内容的学习,您应该能够

  • 在XML schema中创建自定义的数据类型
  • 在XML文档中建立带有属性的空元素
  • 通过使用XML样式表中包含有不同背景颜色、字体以及图形显示的表格来为一个XML文档定义输出形式
  • 使用解析器创建SQL插入命令

概述

编辑
在前面的章节中,我们介绍了简单的XML schema、XML文档、XML样式表以及应用于单一实体模型的简单DOM解析器。接下

来我们将对于XML的关键特征进行更多的介绍。

我们已经在前面几章中介绍了XML schema的一些预定义的数据类型,但是,它还有许多有用的类型,例如URL、日期、时

间、年、月等。除了预定义的数据类型,schema设计者还可以根据特殊的数据输入需要定义其他自定义的数据类型。正如我 们已经学到的,数据通过利用XML schema中定义的标记标签在XML文档中得到表示。但是,有一些元素可能是没有任何取值 的。空元素标签便是用来标记这种元素的。空元素标签(包括其他自定义的标记标签)可以包含属性,这些属性在不增加元素 额外文本的前提下记录了该元素的附加信息。本章将会介绍在空元素标签中使用属性的示例。

XML样式表允许以用户要求的形式显示XML文档内容。在本章中,我们将向你展示如何使用XML样式表中的表格来定义XML文

档显示格式。同时,您也将学会如何定义拥有不同背景颜色、字体大小以及文字对齐方式的显示格式。

正如我们在前面学到的,解析器可以对XML文档进行处理从而实现数据的转换。我们可以利用解析器创建SQL语句,将XML文

档数据插入数据库。在本章中将会提供一个利用DOM解析器创建SQL插入语句的例子。

XML在欧洲中央银行的应用

编辑
在其他的信息中,欧洲中央银行每天都会以XML格式发布欧元与其它货币的汇率。数据以如下的格式进行显示:
<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2004-05-28">
<Cube currency="USD" rate="1.2246"/>
<Cube currency="JPY" rate="135.77"/>
<Cube currency="DKK" rate="7.4380"/>
<Cube currency="GBP" rate="0.66730"/>
<Cube currency="SEK" rate="9.1150"/>
<Cube currency="CHF" rate="1.5304"/>
<Cube currency="ISK" rate="87.72"/>
<Cube currency="NOK" rate="8.2120"/>
</Cube>
</Cube>
</gesmes:Envelope>
为了便于图表显示,我们在上面的代码中省略了一些货币的信息。
银行、咨询师、汇市交易员以及涉及国际贸易的公司都是这些信息的主要使用者。

XML Schema数据类型

编辑
在第二章中,我们介绍了一些常用的数据类型,例如字符串型、十进制型、整型和布尔型。下表中是其他一些有用的类型:

其他数据类型:

类型 格式 示例 备注
year YYYY 1999  
month YYYY-MM 1999-03 当数据元素与日期无关时使用月类型
time hh:mm:ss.sss 还有可选的时区标识 20:14:05 Z代表UTC或-hh:mm或+hh:mm来标识与UTC的差别。这种时间类型用于当你想要表示一个每天都发生的特定时间,例如4:15pm.
date YYYY-MM-DD 1999-03-14  
anyURI 域名的声明由 http://开始 http://www.panpacific.com  
除了预定义的数据类型,我们也可以根据需求创建自定义的数据类型。自定义的数据类型可以是简单的或是复杂的。为了简

便起见,我们创建了一个自定义的简单数据类型,也就是说该元素不包含其他元素或属性,而只包含文本。为了创建一个自定 义的简单数据类型,我们首先需要使用一个预定义的简单类型,在应用该简单类型时,必须附加某些约束来限制相应标签的取 值。自定义的简单数据类型可以被命名,也可以不被命名。如果该自定义的简单数据类型仅使用一次,那么对其命名便毫无意 义;这样,这个自定义的类型只能在给出定义的位置被使用。由于被命名的类型可以重复引用(通过其名称),这样自定义类型可以使用在任何需要的地方。

模式可以用来精确定义元素内容的呈现方式。例如,某些情况下用户可能会需要指定类似电话号码、邮政编码或产品代码之

类的特殊格式。通过为特定元素定义模式,在转换过程中便可以保持数据的统一性,而将相应属性值存入数据库中时也可以保证其与原数据的一致性。

表3-1 中的schema是对前面章节介绍过的schema的扩充,该schema通过两个自定义数据类型,包含了city与hotel之间

的一对多关系.

1:m relationship - City Hotel

Important (newly added) lines are indicated by !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20!
21!
22!
23!
24!
25!
26!
27!
28!
29!
30!
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45!
46!
47!
48
49!
50!
51!
52!
53!
54!
55!
56!
57!
58!
59!
60!
61!
62
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified">
<!-- Tour Guide -->
<xsd:element name="tourGuide">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="city" type="cityDetails" minOccurs="1"
maxOccurs="unbounded"/> 
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- City -->
<xsd:complexType name="cityDetails">
<xsd:sequence>
<xsd:element name="cityName" type="xsd:string"/>
<xsd:element name="adminUnit" type="xsd:string"/>
<xsd:element name="country" type="xsd:string"/>
<xsd:element name="continent">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Asia"/>
<xsd:enumeration value="Africa"/>
<xsd:enumeration value="Australia"/>
<xsd:enumeration value="Europe"/>
<xsd:enumeration value="North America"/>
<xsd:enumeration value="South America"/>
<xsd:enumeration value="Antarctica"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="population" type="xsd:integer"/>
<xsd:element name="area" type="xsd:integer"/>
<xsd:element name="elevation" type="xsd:integer"/>
<xsd:element name="longitude" type="xsd:decimal"/>
<xsd:element name="latitude" type="xsd:decimal"/>
<xsd:element name="description" type="xsd:string"/>
<xsd:element name="history" type="xsd:string"/>
<xsd:element name="hotel" type="hotelDetails" minOccurs="1" 
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<!-- Hotel -->
<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="phone" 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"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

表 3-1: 一对多关系的XML schema – city_hotel.xsd

让我们仔细检视一下上面XML:

  • {20-30}为元素“continent”定义了一个自定义的数据类型。
  • {20}<xsd:simpleType> 标记了该自定义类型定义的开始。注意,在标记中没有定义名称,因此该自定义数据类型是一个

无名称的自定义简单类型。

  • {21}<xsd:restriction base="xsd:string">,字符串xsd:是常用的预定义的简单类型。因此,元素的取值必须是字

符串型。

    • 注意:对于自定义的类型应该定义尽可能多的约束。
  • {22-28}<xsd:enumeration>用来为元素指定一组可接受的取值,以便保持XML文档的一致性。
    • 注意:xsd:定义了可以用于除布尔型之外的所有简单类型的约束,而且指定的取值中可以包含空白字符。
  • {39-40}Hotel是一个定义在City中的复杂类型,其作用在于引入city与hotel之间的一对多的关系。
  • {44-48}定义了一个已命名的自定义的简单类型(emailAddressType)。
  • {46}定义了一个特殊的模式,该模式用来定义包含有emailAddressType元素的内容可能的取值范围。
    • 注意:正则表达式(regex)语言可以用来构建模式。XML schema中的regex语言是基于Perl的规则描述语言的。下面是

其中的一些规则:

. (the period) 任何字符
\d 任何数字t
\D 任何非数字
\w 任何单词(或词数混合)字符
\W 任何非单词字符 (例如. -, +, =)
\s 任何空白 (包括空格, tab, 换行, 和回车)
\S 任何非空白字符
x* 有0个或多个x
(xy)* 有0个或多个xy
x+ 重复至少一次x
x? 有一个或0个x
(xy)? 有一个或0个xy
[abc] 包含一组取值
[0-9] 包含有从0到9的取值范围
x{5} 一行之中有5个x
x{5,} 一行之中至少有5个x
x{5,8} 一行之中至少有5个至多有8个x
(xyz){2} 一行之中正好有2个xyz
对于例子 emailAddressType \w+\W*\w*@{1}\w+\W*\w+.\w+.*\w* 这意味着:
[w+] 至少一个单词(或词数混合)字符, 例如 answer
[W*] 至少一个单词(或词数混合)字符, 例如 -
[w*@{1}] 跟随有任意数目(可以是0)个单词字符 并且一个“@” , 例如my@
[w+] 跟随有至少一个单词字符, 例如 mail
[W*] 跟随有0个,1个或多个非单词字符, 例如 _
[w+.] 至少跟随有一个单词字符, 例如 please.
[w+.*] 0到无限次地跟随有前面的字符串, 例如 opentourism.
[w*] 最终跟随有跟有0个,1个或更多单词字符 例如 org
email地址: answer-my@mail_please.opentourism.org
  • {49-61}定义了复杂类型的简单元素hotelDetails,目的在于定义元素的出现次序及其他信息。
  • {54,57,58}由于postalCode,emailAddress和websiteURL并不是必须出现的标准元素,因此,minOccurs="0"表明

了它们是可选的。

  • 在{44-48}中定义的自定义简单类型emailAddressType,被用作emailAddress{56}元素的数据类型。
除了预定义的数据类型(字符串、整型等)外,为了支持特殊的输入数据可以定

制自定义的数据类型(例如,电话号码)。

参考第二章——实体中利用NetBeans创建XML schema的步骤创建上述schema。

XML文档中带属性的空元素

编辑
根据XML schema中的定义,元素可以拥有不同的内容类型。这些类型是元素内容、混合内容、简单内容和空内容。XML文档

中,在开始和结束标签之间可以包含任何信息。

  • 拥有元素内容的为根元素——在开始和结束标签内的任何内容都是该元素的组成成分。
例如: <tourGuide>
      :
  </tourGuide>
  • 混合内容元素是在开始和结束标签之间拥有文本和其他元素的一类元素。
例如: <restaurant>My favorite restaurant is
  <restaurantName>Provino's Italian Restaurant</restaurantName>
      :
  </restaurant>
  • 简单内容元素是在开始和结束标签之间仅拥有文本的一类元素。
例如: <restaurantName>Provino's Italian Restaurant</restaurantName>
  • 空内容元素,也称空元素,是指在开始和结束标签中不包含任何内容(或者该元素在同一个标签内开始并结束,通过在结束

开始标签前加/实现)。

例如: <hotelPicture filename="pan_pacific.jpg" size="80"
          value="Image of Pan Pacific"/>
当没有必要定义元素内容或描述该元素的信息是固定的时候便可以使用空元素。下面有两个例子。第一,一个是通过其属性

引用相应图片源的图片元素。它没有必要定义其文本内容。第二,对于公司来说拥有者的名字是固定的,这样便可以利用“拥 有者”标签的属性来定义拥有者标签内的相关信息。属性是元信息,即描述元素内容的信息。

属性

  • 有效元素的命名结构同样也适用于属性名
  • 给定元素的所有属性名都必须是唯一的
  • 属性中不能包含符号“<”,可以用字符串‘&lt;’来替代它。
  • 每一个属性必须有名称和取值。(例如,<hotelPicture filename=“pan_pacific.jpg” />, filename是名称而

pan_pacific.jpg 是其取值)

  • 如果取值中包含有引用的语句,引号的形式必须能够和用来结束整个取值定义的引号区别开。(例如,如果双引号是用来表

示整个属性取值的,那么在取值中则应该使用单引号来表示对于其他字符串的引用:<name familiar=”’Jack’” >John Smith</name>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25!
26!
27!
28!
29!
30!
31!
32!
33!
34
35
36!
37!
38!
39!
40!
41!
42!
43!
44!
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65!
66!
67!
68!
69!
70!
71!
72!
73!
74!
75!
76
77
78!
79!
80!
81!
82!
83!
84!
85!
86!
87!
88
89
90
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="city_hotel.xsl" media="screen"?>
<tourGuide xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
xsi:noNamespaceSchemaLocation=
'city_hotel.xsd' >
<city>
<cityName>Belmopa</cityName> 
<adminUnit>Cayo</adminUnit>
<country>Belize</country> 
<continent>South America</continent>
<population>11100</population>
<area>5</area> 
<elevation>130</elevation>
<longitude>12.3</longitude>
<latitude>123.4</latitude>
<description>Belmopan is the capital of Belize</description>
<history>Belmopan was established following devastation of the
former capitol, Belize City , by Hurricane Hattie in
1965. High ground and open space influenced the choice
and ground-breaking began in 1966.  By 1970 most 
government offices and operations had already moved to
the new location.
</history>
<hotel> 
<hotelPicture filename="bull_frog_inn.jpg" size="80"
value="Image of Bull Frog Inn" 
imageURL="http://www.bullfroginn.com"/>
<hotelName>Bull Frog Inn</hotelName> 
<streetAddress>25 Half Moon Avenue</streetAddress>
<phone>501-822-3425</phone>
<emailAddress>bullfrog@btl.net</emailAddress>
<websiteURL>http://www.bullfroginn.com/</websiteURL> 
<hotelRating>4</hotelRating>
</hotel>
<hotel>
<hotelPicture filename="pook_hill_lodge.jpg" size="80" 
value="Image of Pook's Hill Lodge"
imageURL="http://www.global-travel.co.uk/pook1.htm"/>
<hotelName>Pook's Hill Lodge</hotelName>
<streetAddress>Roaring River</streetAddress> 
<phone>440-126-854-1732</phone>
<emailAddress>info@global-travel.co.uk</emailAddress> 
<websiteURL>http://www.global-travel.co.uk/pook1.htm</websiteURL>
<hotelRating>3</hotelRating> 
</hotel>
</city>
<city> 
<cityName>Kuala Lumpur</cityName>
<adminUnit>Selangor</adminUnit> 
<country>Malaysia</country>
<continent>Asia</continent>
<population>1448600</population> 
<area>243</area>
<elevation>111</elevation>    
<longitude>101.71</longitude>
<latitude>3.16</latitude> 
<description>Kuala Lumpur is the capital of Malaysia and is the
largest city in the nation.</description> 
<history>The city was founded in 1857 by Chinese tin miners and
superseded Klang. In 1880 the British government transferred
their headquarters from Klang to Kuala Lumpur , and in 1896
it became the capital of Malaysia .
</history>
<hotel>
<hotelPicture filename="pan_pacific.jpg" size="80" 
value="Image of Pan Pacific"
imageURL="http://www.malaysia-hotels-discount.com/hotels/
kualalumpur/pan_pacific_hotel/index.shtml"/>
<hotelName>Pan Pacific Kuala Lumpur </hotelName>
<streetAddress>Jalan Putra</streetAddress> 
<postalCode>50746</postalCode>
<phone>1-866-260-0402</phone> 
<emailAddress>president@panpacific.com</emailAddress>
<websiteURL>http://www.panpacific.com</websiteURL> 
<hotelRating>5</hotelRating>
</hotel> 
<hotel>
<hotelPicture filename="mandarin_oriental.jpg" size="80" 
value="Image of Mandarin Oriental"
imageURL="http://www.mandarinoriental.com/kualalumpur"/> 
<hotelName>Mandarin Oriental Kuala Lumpur </hotelName>
<streetAddress>Kuala Lumpur City Centre</streetAddress> 
<postalCode>50088</postalCode>
<phone>011-603-2380-8888</phone> 
<emailAddress>mokul-sales@mohg.com</emailAddress>
<websiteURL>http://www.mandarinoriental.com/kualalumpur/</websiteURL>
<hotelRating>5</hotelRating>
</hotel> 
</city>
</tourGuide>

表 3-2: 一对多关系的XML文档 – city_hotel.xml

让我们检视一下在上述XML文档中出现的一些元素:

  • 为该XML文档定义屏幕输出格式的样式表在{2}中声明。
  • 元素“continent”的内容必须为在XML schema中为元素“continent”定义的取值集合中的一个值{10}。
  • 注意,元素hotelDetails不包含postalCode实体。但是文档仍然是有效的,因为postalCode是可选实体。{24-45}
  • 空元素hotelPicture包含有属性“filename”, “size”,和“value”, 这些属性用来记录图片文件的名称以及存储位

置、估量尺寸和关于空元素hotelPicture的描述{25,36,65,78}。

  • 元素emailAddress必须符合schema中的格式定义{32,42,73,85}。

空元素标签中可以包含有记录该标签附加信息的元素属性,同时它还无需向元素添加另外的文本。

参考第二章——单一实体中利用NetBeans创建XML文档的步骤创建上述文档

更多的XML样式表特征

编辑
在上一章中,我们创建了一个样式表,用来简通过HTML页面显示XML文档输出文本。我们可以使用表格工具来规划文档内容

显示所遵循的格式。另外,使用HTML中的样式标签还可以通过定义不同的背景颜色、字体大小以及对齐方式来完成输出页面 的设计。表3-3显示了上面提到的一些属性。注意所有的HTML命令均需大写。

1
2
3
4
5
6
7
8
9!
10!
11!
12!
13!
14!
15!
16!
17
18
19
20!
21!
22
23
24
25
26!
27!
28!
29!
30!
31!
32!
33!
34!
35!
36!
37!
38!
39!
40!
41
42
43
44
45
46
47
48
49!
50!
51!
52!
53!
54!
55!
56!
57!
58!
59!
60!
61!
62!
63!
64!
65
66
67
68
69
70
71
72
73
74!
75!
76!
77!
78!
79!
80!
81!
82
83
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/> 
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE>Tour Guide</TITLE> 
<STYLE TYPE="text/css">
H2 {TEXT-ALIGN:CENTER;} 
.greenBackground {BACKGROUND-COLOR:LIGHTGREEN;
TEXT-ALIGN:CENTER;}
.yellowBackground {BACKGROUND-COLOR:YELLOW; TEXT-ALIGN:CENTER;
FONT-WEIGHT: BOLD ; FONT-SIZE:14pt;}
.salmonBackground {BACKGROUND-COLOR:LIGHTSALMON;
TEXT-ALIGN:CENTER; FONT-SIZE:12pt;}
</STYLE>
</HEAD>
<BODY> 
<H2>Cities and Hotels</H2>
<xsl:apply-templates select="tourGuide"/>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="tourGuide">
<TABLE BORDER="1" WIDTH="100%">
<xsl:for-each select="city">
|-----
| COLSPAN="6" CLASS="greenBackground" | <BR/>
<xsl:text>Continent: </xsl:text>
<xsl:value-of select="continent"/><BR/>
<xsl:text>Country: </xsl:text>
<xsl:value-of select="country"/><BR/>
<xsl:text>Administration Unit: </xsl:text>
<xsl:value-of select="adminUnit"/><BR/>
<xsl:text>City: </xsl:text><xsl:value-of select="cityName"/>
<BR/><BR/>
|----- CLASS="yellowBackground"
|
 || <xsl:text>Hotel Name</xsl:text> || <xsl:text>Street Address</xsl:text>
| <xsl:text>Telephone Number</xsl:text>
| <xsl:text>Email Address</xsl:text> || <xsl:text>Hotel Rating</xsl:text>
<xsl:for-each select="hotel">
|----- CLASS="salmonBackground"
| STYLE="FONT-SIZE:8pt" |
<IMG><xsl:attribute name="SRC">
<xsl:value-of select="hotelPicture/@filename"/>
</xsl:attribute>
<xsl:attribute name="WIDTH">
<xsl:value-of select="hotelPicture/@size"/>
</xsl:attribute>
<xsl:attribute name="HEIGHT">
<xsl:value-of select="hotelPicture/@size"/>
</xsl:attribute>
<xsl:attribute name="ALT">
<xsl:value-of select="hotelPicture/@value"/>
</xsl:attribute>
</IMG>
<BR/>
<xsl:value-of select="hotelPicture/@imageURL"/>
| <xsl:value-of select="hotelName"/>
| <xsl:value-of select="streetAddress"/>
| <xsl:value-of select="telephoneNumber"/>
| <xsl:value-of select="emailAddress"/>
| <xsl:value-of select="hotelRating"/>


</xsl:for-each>
|----- CLASS="salmonBackground"
| COLSPAN="6" STYLE="TEXT-ALIGN:RIGHT" |
<H3><xsl:text>Number of hotel(s) found: </xsl:text>
<xsl:value-of select="count(hotel)"/></H3>


</xsl:for-each>
</TABLE>
</xsl:template>
</xsl:stylesheet>

表3-3:用于一对多关系的XML样式表 – city_hotel.xsl

让我们检视一下上述XML样式表中需要注意的几个地方:

  • {9-17}正如在HTML页面中一样,样式标签可以用来定义不同的颜色、字体大小、字体类型、对齐方式、边界以及其他许多

文本格式属性。

  • 在{21}中的xsl:apply-templates element 调用了一个在{25-82}中定义的模板,该模板定义了HTML页面的显示格

式。

  • {27-80}中有一个xsl:for-each元素hotel嵌套在xsl:for-each元素city中。(用来显示表示所有城市中所有宾馆的元

素hotel的适当信息)

  • {51-63}是用来显示图片的图片标签。
  • {52}在XMl schema中,图片文件的名称以及存储位置被定义为空标签hotelPicture的属性(filename)。为了表明

filename是数据来源,图片标签的src属性必须被定义。

  • {51-60}与src类似,长、宽、高这些属性可以用来定义图片的格式。
  • {77}<xsl:value-of select="count(hotel)"/>, count() 是一个预定义的函数,该函数的作用是计算其中参数所指

定的结点的数目。在此例子中即为宾馆的数目。这表明每个城市的宾馆数目已经被记录在文档中。

结果的输出格式也可以使用XML样式表中的HTML表格工具进行设计。

参考第二章——实体中关于利用NetBeans创建XML样式表的步骤上述样式表。

使用解析器生成SQL插入语句

编辑
请务必在运行NetBeans程序之前设置好其中参数。可以参考第二章中设置参数和运行程序的步骤。
使用下面的代码来对于XML文档进行解析并且输出SQL插入语句。
package Parser_Software;

//import class libraries needed for the parsing
//*NOTE: already included in latest Java SDK 1.4.x
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import java.io.*; //import class for Input/Output
import java.util.Vector; //insert statement cache
public class MySimpleDOMParser
{
//global reference to our DOM object
static Document doc;

//parse given XML file when creating MyParser object
public MySimpleDOMParser(String filename)
{
//create file object that holds the XML file
File file = new File(filename);
try
{
/* THREE steps are needed to create a parser and save the
* document data into a DOM object
* 1. create factory object providing the parser
*/
DocumentBuilderFactory factory
= DocumentBuilderFactory.newInstance();

//2. create parser object building the DOM object
DocumentBuilder parser = factory.newDocumentBuilder();

/* 3. use parse method to create DOM object from the given file
* store the resulting DOM object into the "doc" variable
*/
doc = parser.parse(file);

/* +++NOW YOU CAN CALL ANY METHOD TO WORK WITH THIS DATA+++
* example - printNodes: prints out all nodes in the DOM tree
* - insertStatements: creates strings holding the insert
* statement If the document isn't well-formed, an exception has
* already been thrown and this has been skipped.
*/
System.out.println(file + " is well-formed.");

/* The parsing will only succeed if the XML file was well-formed,
* in anyother case it will throw an exception that is caught 
* by the following catch blocks */
}
catch (SAXException e)
{
System.out.println(file + " is not well-formed.");
}
catch (IOException e)
{
//usually happens if the file was not found
System.out.println("Due to an IOException, " +
"the parser could not check " + file);
}
catch (FactoryConfigurationError e)
{
System.out.println("Could not locate a factory class");
}
catch (ParserConfigurationException e)
{
//the JAXP class library was not loaded correctly
System.out.println("Could not locate a JAXP parser");
}
}

//create, display, and execute insert statements derived from
//the DOM object
public void insertStatements(Node n)
{
String sqlStmt;

//get the node name == table name
String tablename = n.getNodeName();

System.out.println("Creating insert statements for table: "
+ tablename);

//get a list of this nodes children
//(= holding the values to be inserted into table)
NodeList values = n.getChildNodes();

//save the information about the values that are to be
//inserted in a cache
Vector cache = new Vector();

//for every child node do the same - recursive call
for (int i = 0; i < values.getLength(); i++)
{
//browse through the children of the given node   
//(e.g. cityName, adminUnit...)
Node child = values.item(i);

//we're not interested in whitespace-text nodes, so we skip them
if (child.getNodeType() != Node.TEXT_NODE)
{
/* get the text node holding the textual information about
* the parent node e.g. "cityName" has a child text node 
* holding the city's name
*/
String insert = child.getFirstChild().getNodeValue();

//once again: skip whitespace nodes
if (insert.trim().length() != 0)
{
insert = "\""+insert+"\"";
cache.add(insert);
}
}
}//End of for-loop

sqlStmt = "INSERT INTO " + tablename + " VALUES (";
int index = 0;
while (index < cache.size()-1)
{
sqlStmt += cache.get(index) + ", ";
index++;
}
sqlStmt += cache.get(index);
System.out.print(sqlStmt);
System.out.print(");" + "\n\n");
}//End of insertStatements()

public static void main(String[] args)
{
//call this application with the command
//line arguments "file.xml file.xsd"
MySimpleDOMParser p = new MySimpleDOMParser(args[0]);

//get a list of all element nodes "city"
NodeList n = doc.getElementsByTagName("city");

//for each "city" in this node list do the following:
for (int i=0; i<n.getLength(); i++)
{ 
/* call the insertStatements method
* (which will print out the statements and //execute them)
*/
p.insertStatements(n.item(i));
}
}//End of main()

}//End of MySimpleDOMParser class

解析器输出结果:

编辑
c:\XML_Chapter\Chapter_3_One_to_Many\city_hotel.xml is well-formed.
Creating insert statements for table : city
INSERT INTO city VALUES ("Belmopan", "Cayo", "Belize", "South America", "11100", "5", "130", "12.3", "123.4", "Belmopan is the capital of Belize", "Belmopan was established following devastation of the
former capitol, Belize City , by Hurricane Hattie in 1965. High ground
and open space influenced the choice and ground-breaking began in
1966. By 1970 most government offices and operations had already moved
to the new location.
");
Creating insert statements for table : city
INSERT INTO city VALUES ("Kuala Lumpur", "Selangor", "Malaysia", "Asia", "1448600", "243", "111", "101.71", "3.16", "Kuala Lumpur is the capital of Malaysia and is the largest city in the nation.", "The city was founded in 1857 by Chinese tin miners and superseded
Klang. In 1880 the British government transferred their headquarters
from Klang to Kuala Lumpur , and in 1896 it became the capital of Malaysia.
");
解析器可以将XML文档进行转换并且将数据插入到关系数据库中。

总结

编辑
除了简单的语定义数据类型(例如,年、月、时间、anyURL和日期)之外,schema的设计人员还可以根据需要创建自定义

的数据类型。简单的自定义数据类型的创建,可以通过对预定义数据类型附加约束、定义取值集合或特定的模式来完成。

空元素不包含任何文本,但是它可以有用来记录元素相关信息的属性。
对于HTML页面显示格式的定义可以包括样式标签、背景颜色、字体大小、对齐方式。表格标签可以用来组织HTML页面中文

档内容的输出格式,使用了图片标签后,图片也可以显示在页面中。

使用解析器,可以生成用来将XML文档中数据保存在关系数据库中的SQL插入语句。

习题

编辑

1. 博物馆通常会有不同的开馆、闭馆日期以及在工作日中的营业时间,同时一些博物馆在周末并不开放。所以应该 创建一个存储相关信息的日程实体来更好的记录博物馆的营业时间。

a. 创建一个描述博物馆的XML schema(使用在上一章中定义的博物馆实体的元素,并且在其中添加一个国家元素。定义这

些元素的可取值集合,比如国家(参见country.xsd http://www.opentoURLsm.org/xmltext/country.xsd)、日 程、开馆时间、闭馆时间等。并且进行良构性及有效性检查。

b. 使用schema创建XML文档,并且填入两个博物馆的数据,要求其中一个博物馆的开放日程中包含五个不同的时间,另一

个包含七个不同的时间。并进行良构性和有效性检查。

c. 按照如下的显示方式编写XML样式表,选择三种不同的背景颜色,2种字体,并且显示出博物馆开放日程中总计划天数。

Insert an image of the museum – width = 80 pixels & height = 70 pixels

 

Museum Name:

Country:

 

Date

Opening Time

Closing Time

Example: 03/01/04

9:00 a.m.

7:00 p.m.

 .

 

 

Number of Calendar Days Found: __

d. 编写一个解析XML文档并且为日程实体生成SQL插入语句的java程序。

2. 导游很有可能需要进行货币的兑换。

a. 帮助他们建立一个用来描述货币代码(例如,EUR代表欧元)的良构的、有效的XML schema。汇率元素应该由3个字母

构成。在其中应该记录有国家(例如,德国)以及相应货币(例如,欧元)的名称。创建一个记录有一部分汇率代码的XML文 档。(在http://www.xe.com/iso4217.htm中您将找到基于ISO4217标准http://www.opentoURLsm.org/ xmltext/curreny.xsd的所有国家货币的代码。)

b. 使用Netbeans来验证XML代码的有效性。尝试使用多于3个字母来描述货币代码(例如,用GBxp代替GBP)。请注意利

用NetBean进行有效性检验时所产生的错误信息。

c.使用XML样式表来生成HTML格式的输出文件。另外在最后需要显示不同货币的总数。输出的形式应该如下图所示:
currency code country currency name
EUR Germany Euro
... ... ...

Number of different currencies found: __

d. 登陆google并且下载表格中所列不同国家的国旗。通过使用带属性的空元素将它们(链接)包含在XML文件和HTML输出

页面中。