XML/单一实体
学习目标
编辑完成本章内容的学习,对于一个实体您将能够
- 创建一个XML数据schema
- 创建一个XML文档
- 创建一个XML样式表
- 编写一段java程序来解析一个XML文档并列出其中的内容
概述
编辑- 许多计算机系统中都会包含有格式不一数据。在这样的系统之间进行数据格式的转换将会耗费大量的时间。XML是一种通用的数据存储格
式,而与之相配套的大量工具和技术能够使得不兼容的系统之间特定XML应用的交换变得十分简捷。由于XML的开放性和通用性,可以预见 的是随着时间的发展,越来越多的组织和个人包括程序员和数据用户都将会选择XML。这将使得XML最终成为对于特定数据交换的最可行的 技术。
- XML不仅仅是被用来进行信息的交换,其也能用于网页的发布。XML的语法非常严谨,从而使得网页浏览器变得体积更小、速度更快成为可
能,同时其也能很好地应用于个人数字助理(DA)和手机上。而在另一方面,为读取HTML格式网页而设计的浏览器,往往必须设计大量的 代码来解决由于HTML缺乏对于数据格式的严格定义而造成的不便。
- 适用于以XML方式进行编码的数据类型应该具有以下特点:域长度是未知的和不可预见的,这里域的内容大多数为纯文本。
- XML schema 允许以标准化结构进行信息交换。 Schema定义了一些自定义的标记,这些标记包含有许多用以描述标记所标识内容的属
性。这样,XML文档中被标记的数据中所包含的信息便可以通过一种名叫“解析器”的应用程序进行提取,更进一步,利用XML样式表便可以转 换为Web网页格式。
- 创建schema的第一步便是定义描述数据交换中所涉及事实的数据模型。当具有高置信度的模型一旦被创建,数据模型便可以转换成为
schema。在本章内容中,我们将从一个简单的例子开始,在其后的章节中将会陆续介绍XML其他更加复杂的属性。
- 如下图所示,我们将会从一个单一的实体CITY开始。由于本章讨论的是将单一的实体CITY映射到XML schema的问题,我们需要定义一个
包含CITY的实体TOURGUIDE。我们可以将TOURGUIDE想象成为一个包含有许多城市的实体,并且TOURGUIDE将不包含任何属性或是标 签。TOURGUIDE将仅仅是一个城市相关数据的集合。
XML schema
编辑XML schema 描述了XML文档的结构和内容,其定义了:
- 出现在一个文档中的所有元素的名称和内容;
- 文档的结构;
- 所有的子元素;
- 子元素的数目;
- 元素出现的频率;
- 元素出现的顺序;
- 元素的数据类型.
- XML schema的一个突出的优点是它定义了数据类型,使得对于符合该Schema的文档的内容描述和数据正确性的校验变得更加容易。这样
一来,文档中可能包含的错误就能够在进行数据交换之前被检测出。
- XML schema语言被称为XML schema 定义(XSD)。因为XML schema也是用XML编写的,所以它是可扩展的,而且XML文档的编辑器
可同样用于XML schema的编辑。
- 通用XML schema数据类型
XML schema有许多预定义的数据类型。最为通用的有:
- 字符串型——元素中包含有一串字符
- 十进制型——元素中包含有十进制小数
- 整型——元素中包含有整数
- 布尔型——元素中包含有真/假或1/0
- 日期型——元素中包含有日期
- 时间型——元素中包含有时间
- uri引用型——元素中包含有URL(统一资源定位符)
- 完整的预定义数据结构列表请参http://www.w3.org/TR/xmlschema-2/#built-in-datatypes
- schema元素的定义有两种类型:简单或复杂。一个“简单类型”将只包含“文本”而不会有其他元素或属性。在这里,“文本”是一个概括的表示,其含义是预定义的数据类型或来源于用户自定义的类型定义。一个“复杂类型”包含有其他的元素或属性。无论简单还是复杂的类型都可以进行命名,以便能够在schema的其他部分进行重用;如果不对该类型命名,则该类型只有在给出定义的元素下才能被使用。
<xsd:element name="city" type="cityDetails">
<xsd:complexType name="cityDetails">
<xsd:sequence>
<xsd:element name="cityName" type="xsd:string"/>
<xsd:element name="adminUnit" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
图2-1 命名的复杂类型
<xsd:element name="tourGuide">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="city" type="cityDetails"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
图2-2 未命名的复杂类型
<?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="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:sequence>
</xsd:complexType>
</xsd:schema>
表2-1 City实体的XML schema – city.xsd
让我们检查一下上面的XML schema
- 所有的XML文档都以XML声明开始{1}。
- XSD schema 命名空间namespace 声明 {2}. 命名空间将会在《数据schema》[[Data schemas
(XML) | Data schemas]] 章节中深入地讨论。
- 注释被包含在标签“<!--“和“-->” 之间{3}.
- tourGuide元素被定义为一个复杂类型{4-10},也就是说其中包含嵌入的元素。
- 一个元素最少出现次数通过minOccurs(默认值为1)进行定义,最大出现次数没有限制maxOccurs=“无穷大”{7}
- City被声明为已命名的复杂类型{7}。
- <xsd:complexType 标志了一个复杂类型声明的开始{12},”cityDetails” 标识了这个复杂类型。但是这不是该
复杂类型的名称。这种复杂类型定义可以用来对于多个元素进行声明。
- Schema元素sequence {13} 定义了子元素出现的次序。
- <xsd:element 标志了一个简单类型声明的开始{14}。”cityName” 是这个被声明的元素的名称(在XML文档中通常
以<cityName>的形式出现)”xsd:string” 是这个元素的数据类型。
- 结束标志{24-26}。注意:结束标志不能相互交叠。
- 注意: 纬度和经度是十进制数据类型。从通常形式(例如50º 17' 35")到十进制形式的转换可通过公式度+分/60+秒/3600。
- 对于任何XML文档,包括XML schema和XML 样式表文档,都可以进行检查以判定它们是否“结构良好”(良构)。正如第一
章所描述的,一个符合XML语法规则的XML文档就是良构的文档,即有且只有唯一的一个根元素,任何开始标签必须有一个结 束标签与之对应。我们可使用XML编辑软件来进行结构良好性检验,例如NetBeans。
- 一旦检查到错误,这些错误将会按顺序显示在结果窗口中。双击任何一个错误报告,便可以转到XML文档中该错误出现的位置。
可以使用NetBeans创建上述XML schema:
- 点击File -> New -> XML -> XML Schema。
- 将文件保存为“city”(将自动添加后缀.xsd)。
- 复制并粘贴上述schema到文件city.xsd中并保存。
检查XML文档是否为良构的:
- 右键单击文档节点,选择Check XML document 或按Alt+F9。
如果XML schema city.xsd是良构的,输出窗口将如下所示:
小结:XML schema 显示了XML文档的元素和结构
XML文档
编辑- XML文档是包含有XML代码和句法的文件。所有的XML文档必须包含有唯一一对标识"根"元素的标签。所有其他元素都必须包
含在这个根元素中。元素可以拥有子元素。相对应的,任意子元素都有一个“父”元素。所有的元素都必须正确地嵌套在它们的父元素中,也就是子元素的结束标签一定要在父元素结束标签前给出。这样便形成了一个树状的结构。XML文档以.xml为后 缀。
XML元素命名规定
- XML元素的名称必须以字母或带下划线的字符开头。而且也不能以字符串“xml”开头,“xml”是XML定义保留的字符串。
名称的其他部分可以是字母、数字或其他字符但中间不能存在空格。理论上讲可以给元素定义任意名称,但是为了增强元素名的描述性,名称最好能够反映该元素的所表示的内容。
- XML文档通常会有一个相对应的数据库,在该数据库中字段与XML文档中的元素相对应。一个很好的方式是使用数据库中的命
名规则来进行XML文档元素的命名。
- “:”尽量不要用在元素的名称之中。因为其是被保留用来进行命名空间的定义(这一部分将会在下一章中详细介绍)
<?xml version="1.0" encoding="UTF-8"?>
<tourGuide
xmlns:xsi='http://www.w3.org/1/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='city.xsd'>
<city>
<cityName>Belmopan</cityName>
<adminUnit>Cayo</adminUnit>
<country>Belize</country>
<population>
/population>
<area>
5
</area>
<elevation></elevation>
<longitude>
/longitude>
<latitude>
/latitude>
<description>Belmopan is the capital of Belize</description>
<history>Belmopan was established following the devastation of the former capitol,
Belize City, by Hurricane Hattie in 5. High ground and open space influenced the
choice and ground-breaking began in 6. By 0 most government offices and
operations had already moved to the new location.</history>
</city>
<city>
<cityName>Kuala Lumpur</cityName>
<adminUnit>Selangor</adminUnit>
<country>Malaysia</country>
<population>0</population>
<area>
</area>
<elevation></elevation>
<longitude>
./longitude>
<latitude>
3./latitude>
<description>Kuala Lumpur is the capital of Malaysia and the largest city in the nation</description>
<history>The city was founded in 7 by Chinese tin miners and superseded Klang. In
0 the British government transferred their headquarters from Klang to Kuala Lumpur,
and in 6 it became the capital of Malaysia. </history>
</city>
</tourGuide>
表2-2 City 实体的XML文档 – city.xml
表2-2中列出了用来描述拥有一个city实体的tourGuide的XML文档。需要注意以下几点:
- 每一个XML文档的第一行都以XML声明开始{1}。
- 随后的的声明标明了该文档的根元素(tourGuide)以及schema文件(city.xsd),该声明使用xsi=schemaLocation {2-4}。
- 对于第一个城市{5-19}和第二个城市{20-33}的定义。
- 根元素的结束标签{34}。
- 由XML schema约束的XML文档可以进行有效性验证。一个“有效”的XML文档是一个“结构良好”的XML文档,也就是说其也遵循了XMLschema中的规则。但是,需要注意的是即使文档是结构良好的,其仍有可能是无效的。例如,如下的XML文档片断:
<city> <cityName>Boston</cityName> <country>United States</country> <adminUnit>Massachusetts</adminUnit> ...... </city>
- 我们可以看到,元素并没有按照Schema中规定的正确顺序出现。依据其声明的schema,该XML文档可以(使用检验程序)进行有效性检验——检验程序将会发现上面提到的顺序混乱的错误。
使用NetBeans创建上述的XML文档:
- 点击File -> New -> XML -> XML Document。
- 将文件保存为“city”。
- 选择XML Schema-Constrained Document 作为文档的类型。
- 定义schema位置以及跟元素的名称(tourGuide)。
- 复制并粘贴上述代码并保存。
- 进行良构性检验(ALT+F9)
进行有效性检验:
- 右键单击文档节点选择Validate XML。
如果XML文件city.xml,遵循了XMLschema city.xsd的定义,则输出窗口将显示如下信息:
- 在NetBeans中打开文档city.xml
小结:XML文档是一个包含有XML代码和句法的文件,是一个由元素及子元素良好组织而形成的实体。 |
XML 样式表
编辑- 可扩展样式表语言(XSL)为XML文档的转换以及以特定格式显示内容提供了一种手段。由于XML文档并没有提供浏览器能够理解的标签,比如HTML标签,没有包含了表达信息的样式表的辅助,浏览器便无法显示出XML文档中的数据。通过将数据与表示逻辑相分离,XSL允许用户根据其不同的需要和偏好浏览同样的数据。
- XSL转换语言(XSLT)被用来进行XML文档的转换,例如将XML文档转换为用于浏览器浏览的HTML文件。XSLT样式表包含有一组格式说明,这些格式说明规定了XML文档内容在浏览器中的显示方式,这一点与HTML的级联样式表(CSS)十分相似。使用不同的样式表对于同样的数据可以产生不同的视图。而且样式表不是仅仅用于浏览器显示文档内容,例如,样式表也可以用于XML文件的转换。
- 在文件转换过程中,XSLT对XML文件进行分析,并将其转化为一个节点树,即XML文档的一种层次化的表示。树中的每一个节点代表了一个XML文档片断,例如一个元素、属性或其他的文本内容。XSL样式表包含有预定义的“模板”,这些模板定义了对于节点的操作。XSLT会通过匹配属性将XML元素与模板联系起来,并且将其转换成结果文档。
1. <?xml version="1.0" encoding="UTF-8"?> 2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 3. <xsl:output method="html"/> 4. <xsl:template match="/"> 5. <HTML> 6. <HEAD> 7. <TITLE>Tour Guide</TITLE> 8. </HEAD> 9. <BODY> 10. <H2>Cities</H2> 11. <xsl:apply-templates select="tourGuide"/> 12. </BODY> 13. </HTML> 14. </xsl:template> 15. <xsl:template match="tourGuide"> 16. <xsl:for-each select="city"> 17. <xsl:text>City: </xsl:text> 18. <xsl:value-of select="cityName"/> 19. <BR/> 20. <xsl:text>Population: </xsl:text> 21. <xsl:value-of select="population"/> 22. <BR/> 23. <xsl:text>Country: </xsl:text> 24. <xsl:value-of select="country"/> 25. <BR/> 26. <BR/> 27. </xsl:for-each> 28. </xsl:template> 29. </xsl:stylesheet> |
表2-3 City实体的XML样式表 – city.xsl
让我们分析一下上面的样式表:
- 由于XSLT使用XML语言编写的,它们总是以标准的XML声明加上XML句法规格开头。
- 标签<xsl:stylesheet> 标明了样式表定义的开始,并且声明了版本号以及W3C的正式命名空间{2,3}。
- 元素<xsl:template>定义了一个模板定义的开始,并且包含了对于匹配节点的操作规则的定义。匹配规则被用来将XML元素与样式表进
行匹配。在上面的样式表中即为XML原文档的根(/)或整个分支{4}。XSL查找匹配的根然后输出HTML文件。
- 模板元素内容包含在HTML数据输出流中,这样浏览器便可以进行相应的解释{5-18}。
- XSL<xsl:for-each>元素被用来对于一个特定节点集(此例中为元素city)中的所有节点进行遍历,并将其加入到输出文件中{28}。
- <xsl:value-of>元素从被选节点/XML元素(cityName)中提取属性值,并将其加入到输出数据流中。{18,21,24}
city.xsl样式表的输出结果如表2-3所示:
Cities
City: Belmopan
Population: 11100
Country: Belize
City: Kuala Lumpur
Population: 1448600
使用NetBeans创建XML样式表的步骤如下:
- 点击File -> New -> XML -> XSL Stylesheet
- 将文件保存为“city”
- 复制并粘贴上述代码到NetBeans编辑器,并保存。
- 对于样式表进行格式良构性检查。(ALT+F9)
- 注意:作为示例的city系列文件(city.xsd, city.xml and city.xsl)也可以通过文本编辑器创建,并且结果能够利用合适的浏览器例如Mozilla 1.6进行显示。但是应该将所有的文件保存在同一个目录下并且在city.xml第一行中加入如下的代码:
<?xml-stylesheet href="city.xsl" type="text/xsl"?>
该行代码便将XSL样式表与包含有城市数据的XML文件建立起关联。
小结:XSL是一种用来将信息转换成可表示形式的工具,而且同时还保持数据的含义。 |
XML在 Thomas Cook中的应用
编辑
XML使得同样的工作能够在3天之内得到完成。这使得Thomas Cook所有的当前或潜在客户以及分布在世界各地的代理商能够获取实时的旅游信息。而以前他们至少需要等待6周的时间。
XML格式的宣传网页以及旅游指南和在线杂志。
提高,而这为ThomasCook提供了微弱的竞争优势。
|
解析XML文档
编辑- 我们已经学习了如何表示数据,接下来我们需要的就是处理该数据。这项工作能够利用一种叫做XML解析器的软件来实现,XML解析器能够读取XML文档并且对照XML schema进行有效性检验。XML解析器使得人们对于XML文档的内容和结构可以有更
好的了解。它支持XSLT标准,能够将数据细分并传递给其他的应用程序或转换成其他格式,例如HTML。
解析器类型:
DOM (Document Object Model 文档目标模型) – 此类解析器将整个XML文档读入内存,依据XML文档创建目标树结构然后等待用户的指令。这种方式将受到内存容量的限制因为XML文档大小有可能超出内存的容量。
SAX, the Simple API for XML 简单XML应用程序接口, 它是一个基于事件的解析器。此类解析器逐行读取XML文档,并在发现任一目标元素时产生一个事件。例如,每个XML根标签都会伴随一个“start element”事件。SAX解析器在任 一时刻只会为客户程序处理文档的一个或几个片断。当发现所需元素时,它便会从文档中返回数据。对于大型XML文档来说,SAX提供了在小内存占用量条件下更快和更高效解析XML数据的方法。
- 我们需要针对应用的特点选择DOM(基于树)或SAX(基于事件)解析方式。但是,从本书的写作初衷出发,我们使用一种开放源码的基于DOM的解析器——Xerces Java。Xerces Java能够利用DOM方便地读取文档数据并进行诸如添加、删除节点的
操作。Xerces Java由apache.org发起并开发。
- 下面是用来进行解析的XML文档代码。解析的结果是根据文档得到的DOM树。该java程序由Hendrik Fischer编写。
(NOTE from Klaas van Gelder (klaasvg@fastmail.fm): the class TypeTranslator does not exist in one of the imported packages, so the code does not compile...)
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"); } } //print out the nodes starting at a given node (usually the root node) public static void printNode(Node n) { //gather information about the current node name String name = n.getNodeName(); String type = TypeTranslator.getTypeName(n); String uri = n.getNamespaceURI(); String value = n.getNodeValue(); //put results into a string buffer StringBuffer output = new StringBuffer(); output.append("Node : " + name + "\n"); output.append("Type : " + type + "\n"); if (uri != null) output.append("NameSpace : " + uri + "\n"); if (value != null) output.append("Value : " + value + "\n"); //display the result to the user System.out.println(output.toString()); //get a list of the current node's children in the DOM tree NodeList children = n.getChildNodes(); //for every child node do the same - recursive call for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); printNode(child); } }//End of printNode() 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"); printNode(doc); }//End of main() }//End of MySimpleDOMParser class |
使用NetBeans创建并运行XML解析器:
首先,必须创建一个存放java文件的包。
- 点击File -> New -> Java Package。
- 保存为“'Parser_Software”
然后创建java文件:
- 点击File -> New -> Java Classes -> Java Class。
- 在java文件包中保存为“MySimpleDOMParser”——创建命名的解析器。
- 复制并粘贴上面的代码。
- 点击Build -> Set Arguments...
- 输入XML文档的准确路径。例如,c:\XML_Chapter\Chapter_2_Single_entity\city.xml
- 点击Build -> Execute,执行操作
解析器输出结果:
编辑
|
小结:解析器程序使得用户可以方便地访问XML文档的内容和结构,并且允许用户对于解析器本身进行处理和修正。 |
总结
编辑- XML(可扩展标记语言)是一种在文本文件中以结构化方式描述数据的方法。它主要用于信息的交换。XML是基于网络的、可扩展的、独立于平台的语言,它是构建所有XML文档的基础。
- XML schema 描述了XML文档的内容和结构。XML文档包含了数据,而XML样式表定义用于XML文档表示的格式说明。一个结构良好的XML文档完全遵循了XML句法,而如果文档同时遵循了相应的XMLschema,那么它就是有效的。
- 基于DOM的解析器在内存中为待解析的XML文档建立了一个树结构,而SAX则是逐步读取文档数据并在发现标签、文本或注释时报告用户。
练习
编辑1. 一个博物馆的问题。
- a. 创建一个用来描述博物馆实体的XML schema,该实体拥有以下属性:博物馆名称、建馆日期、地址、网址。并进行良构性和有效性验证。
- b. 利用刚才创建的schema创建XML文档,使其包含有两个博物馆的数据。并进行良构性和有效性验证。
- c. 编写XML样式表来显示博物馆的名称、建馆日期和网址。并进行良构性和有效性验证。
- d. 编写一段java程序来对XML文档进行解析并列出每个博物馆的名称和地址。
2. XML数据流程图模型。
建立包含以下组件的数据流程图并解释其如何工作:
- XSL样式表
- XML文档
- XML schema
- XSL(T)处理器
- 不同的输出结果
练习2的参考答案: