“核心技术Ⅱ:XML”的版本间差异
跳到导航
跳到搜索
无编辑摘要 |
|||
第163行: | 第163行: | ||
== 解析XML文档 == | == 解析XML文档 == | ||
xml解析器:读入一个文件,确认这个文件具有正确的格式(验证xml文档),然后将其分解成各种元素,使得程序员能够访问这些元素;<br/> | |||
* Java 库提供了两种XML 韶析器: | |||
*# “'''树型解析器'''”:将读入的XML 文档转换成'''树结构'''。 | |||
*#: 如:文档对象校型(Document Object Model, DOM)解析器; | |||
*# “'''流机制解析器'''”:在读入XML 文档时生成相应的'''事件'''。 | |||
*#: 如:XML 简单API(Simple API for XML, SAX)解析器; | |||
* 何时使用“流机制解析器”: | |||
*# 如果需要处理很长的文档,若生成树结构将会消耗大量内存; | |||
*# 或者如果只对某些元素感兴趣,而不关心它们的上下文; | |||
=== 树型解析器 === | |||
<pre> | |||
DOM 韶析器的接门已经被W3C 标准化了。org.w3c.dom 包中包含了这些接口类型的定义,比如: Document 和Element 等。不同的提供者,比如Apache 组织和IBM, 都编写了实现这些接口的DOM 解析器。 | |||
</pre> | |||
Java XML 处理 API (Java API for XML Processing, '''JAXP''') 库使得我们实际上可以以插件形式使用这些韶析器中的任意一个。 | |||
* JDK 中也包含了从Apache 解析器导出的DOM 解析器; | |||
读人XML文档: | |||
# 首先需要“'''DocumentBuilder'''”对象(从“'''DocumentBuilderFactory'''”中得到): | |||
#: <syntaxhighlight lang="java"> | |||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | |||
DocumentBuilder builder = factory.newDocumentBuilder(); | |||
</syntaxhighlight> | |||
# 从不同的源中读入文档: | |||
#: <syntaxhighlight lang="java"> | |||
// 从文件: | |||
File f = ... | |||
Document doc = builder.parse(f); | |||
// 从一个URL: | |||
URL u = ... | |||
Document doc= builder.parse(u); | |||
// 从指定的输入流: | |||
InputStream in = ... | |||
Document doc= builder.parse(in); | |||
</syntaxhighlight> | |||
#* 果使用输入流作为源,那么对于那些以该文档的位置为相对路径而被引用的文档,解析器将无法定位。 | |||
* “'''Document'''”对象是XML 文档的树型结构在内存中的表示方式,它由实现了“'''Node'''”接口及其各种子接口的类的对象构成: | |||
*: [[File:Node接口及其子接口.png|500px]] | |||
解析文档内容: | |||
# 调用“'''getDocumentElement'''”方法,获取文档根元素: | |||
#: 调用“'''getTagName'''”方法可以返同元素的标签名; | |||
#: <syntaxhighlight lang="java"> | |||
Element root = doc.getDocumentElement(); | |||
String rootName = root.getTagName(); | |||
</syntaxhighlight> | |||
# 调用“'''getChildNode'''”方法,获取元素的子元素(可能是子元素、文本、注释或其他节点): | |||
#: 返回一个类型为“Nodelist”的集合; | |||
#: “item”方法将得到指定索引俏的项; | |||
#: “getLength”方法则提供了项的总数; | |||
#: <syntaxhighlight lang="java"> | |||
// 枚举所有子元素 | |||
// 得到的子元素会包含:元素之间的“\n”等空白字符 | |||
Nodelist children = root.getChildNodes(); | |||
for (int i = O; i < children.getlength(); i++) | |||
{ | |||
Node child= children.item(i); | |||
... | |||
} | |||
// 枚举所有子元素 | |||
// 并忽略元素之间的“\n”等空白字符 | |||
Nodelist children = root.getChildNodes(); | |||
for (int i = O; i < children.getlength(); i++) | |||
{ | |||
Node child= children.item(i); | |||
if (chi1d instanceof Element) | |||
{ | |||
Element childElement = (Element) child; | |||
... | |||
} | |||
} | |||
</syntaxhighlight> | |||
#* 利用DTD,解析器会忽略空白字符; | |||
# | |||
#: <syntaxhighlight lang="java"> | |||
</syntaxhighlight> | |||
# | |||
#: <syntaxhighlight lang="java"> | |||
</syntaxhighlight> | |||
# | |||
#: <syntaxhighlight lang="java"> | |||
</syntaxhighlight> | |||
# | |||
#: <syntaxhighlight lang="java"> | |||
</syntaxhighlight> | |||
==== 使用“XPath”来定位信息 ==== | ==== 使用“XPath”来定位信息 ==== | ||
第176行: | 第268行: | ||
=== 使用命名空间 === | === 使用命名空间 === | ||
== 验证XML文档 == | == 验证XML文档 == |
2020年11月26日 (四) 18:55的版本
XML概述
XML 是一种非常有用的描述结构化信息的技术。
“Properties”类:在单个方法调用中读入这样的“属性文件”(property file):
- 属性文件:用于描述程序配置;包含了一组“名/值”对:
fontname=Times Roman fontsize=l2 windowsize=400 200 co1or=O 5O 100
但是:
- 属性文件采用的是一种单一的平面层次结构;所以常常会出现这种情况:
title.fontname=Helvetica title.fontsize=36 body.fontname=Times Roman body.fontsize=12
- 属性文件要求键是唯一的;所以保存序列值需要:
menu.item.l=Times Roman menu.item.2=Helvetica menu.item.3=Goudy Old Style
XML 和HTML 格式是古老的标准通用标记语言(Standard Generalized Markup Language, SGML) 的衍生语言。
- XML 格式能够表达层次结构,并且重复的元素不会被曲解:
<configuration>
<title>
<font>
<name>Helvetica</name>
<Size>36</size>
</font>
</title>
<body>
<font>
<name>Times Roman</name>
<Size>12</size>
</font>
</body>
<window>
<width>400</width>
<height>200</height>
</window>
<color>
<red>O</red>
<green>50</green>
<blue> 100</blue>
</color>
<menu>
<item>Times Roman</item>
<item>Helvetica</item>
<item>Goudy 01d Style</item>
</menu>
</configuration>
XML 和HTML的区别:
XML | HTML |
---|---|
大小写敏感
如:<H1> 和<hl> 是不同的XML 标签 |
不敏感 |
结束标签绝对不能省略 | 如果从上下文中可以分清哪里是段落或列表项的结尾,那么结束标签(如</p>或</li>) 就可以省略 |
只有单个标签而没有相对应的结束标签的元素必须以“/”结尾
如:<img src="coffeecup.png"/ > |
|
属性值必须用引号括起来
如:<applet code="MyApplet.class" width="300" height="300"> |
引号是可有可无的
如:<applet code="MyApplet.class" width=300 height=300> |
所有属性必须都有属性值
如:<input type="radio" name="1anguage" value="Java" checked="checked"> |
属性名可以没有值
如:<input type="radio" name="1anguage" value="Java" checked> |
XML 文档的结构
- XML 文档应当以一个文档头开始:
<?xml version="l.O"?> 或 <?xml version="l.O" encoding="UTF-8"?>
- 文档头之后通常是文档类型定义(Docun1ent Type Definition, DTD):
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//OTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
- XML 文档的正文包含根元素,根元素包含其他元素:
<?xml version="l.O"?> <!DOCTYPE configuration ... > <configuration> <title> <font> <name>Helvetica</name> <Size>36</size> </font> </title> ... </configuration>
- 元素可以有子元素(child element )、文本或两者皆有;
- 在设计XML 文档结构时,应避免混合式内容(mixed content),以简化解析过程:
<font> Helvetica <Size>36</size> </font>
- XML元素可以包含属性,但属性的灵活性要差很多;
- “属性只应该用来修改值的解释,而不是用来指定值。”
- “HTML 中,凡是不显示在网页上的都是属性。”
<font name="Helvetica" size="36 pt"/> <font> <name>Helvetica</name> <Size unit="pt">36</size> </font>
XML中的其他一些标记:
- 字符引用(character reference):形式是“&#”十进制值;或“&#x”十六进制值;
- 实体引用(entity reference):形式是“&name”;
下面这些实体引用: < > & " ' 都有预定义的含义: 小于、大于、&、引号、省略号等字符。
- CDATA部分(CDATA Section):用“<![CDATA[”和“]]>”来限定其界限;
- 它们是字符数据的一种特殊形式。可以使用它们来襄括那些含有“<”、“>”、“&”之类字符的字符串,而不必将它们解释为标记;
- CDATA 部分不能包含字符串“]]>”;
<![CDATA[< & > are my favorite delimiters]]>
- 处理指令(processing instruction):是那些专门在处理XML 文档的应用程序中使用的指令,它们由“<?”和“?>”来限定其界限:
<?xml-stylesheet href="mystyle.css" type="text/css"?> 每个XML 都以一个处理指令开头: <?xml version="l.O"?>
- 注释(comment):用“<!-”和“-->”限定其界限:
- 注释不应该含有字符串“--”;
<!-- This is a comment. -->
解析XML文档
xml解析器:读入一个文件,确认这个文件具有正确的格式(验证xml文档),然后将其分解成各种元素,使得程序员能够访问这些元素;
- Java 库提供了两种XML 韶析器:
- “树型解析器”:将读入的XML 文档转换成树结构。
- 如:文档对象校型(Document Object Model, DOM)解析器;
- “流机制解析器”:在读入XML 文档时生成相应的事件。
- 如:XML 简单API(Simple API for XML, SAX)解析器;
- “树型解析器”:将读入的XML 文档转换成树结构。
- 何时使用“流机制解析器”:
- 如果需要处理很长的文档,若生成树结构将会消耗大量内存;
- 或者如果只对某些元素感兴趣,而不关心它们的上下文;
树型解析器
DOM 韶析器的接门已经被W3C 标准化了。org.w3c.dom 包中包含了这些接口类型的定义,比如: Document 和Element 等。不同的提供者,比如Apache 组织和IBM, 都编写了实现这些接口的DOM 解析器。
Java XML 处理 API (Java API for XML Processing, JAXP) 库使得我们实际上可以以插件形式使用这些韶析器中的任意一个。
- JDK 中也包含了从Apache 解析器导出的DOM 解析器;
读人XML文档:
- 首先需要“DocumentBuilder”对象(从“DocumentBuilderFactory”中得到):
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder();
- 从不同的源中读入文档:
// 从文件: File f = ... Document doc = builder.parse(f); // 从一个URL: URL u = ... Document doc= builder.parse(u); // 从指定的输入流: InputStream in = ... Document doc= builder.parse(in);
- 果使用输入流作为源,那么对于那些以该文档的位置为相对路径而被引用的文档,解析器将无法定位。
解析文档内容:
- 调用“getDocumentElement”方法,获取文档根元素:
- 调用“getTagName”方法可以返同元素的标签名;
Element root = doc.getDocumentElement(); String rootName = root.getTagName();
- 调用“getChildNode”方法,获取元素的子元素(可能是子元素、文本、注释或其他节点):
- 返回一个类型为“Nodelist”的集合;
- “item”方法将得到指定索引俏的项;
- “getLength”方法则提供了项的总数;
// 枚举所有子元素 // 得到的子元素会包含:元素之间的“\n”等空白字符 Nodelist children = root.getChildNodes(); for (int i = O; i < children.getlength(); i++) { Node child= children.item(i); ... } // 枚举所有子元素 // 并忽略元素之间的“\n”等空白字符 Nodelist children = root.getChildNodes(); for (int i = O; i < children.getlength(); i++) { Node child= children.item(i); if (chi1d instanceof Element) { Element childElement = (Element) child; ... } }
- 利用DTD,解析器会忽略空白字符;
-
-
-
-