2007-12-11 23:07:06| 分类: Java |举报 |字号 订阅
Java的API中提供了许多能有效地操作xml的类。这些类遵循了通用的国际标准。若干标准中使用最多是DOM,即Document Object Model,文档对象模型。它的基本思路是,把xml文件对应到内存中的一个xml树。通过对父、子、兄弟等的关系的访问可很方便地在各个结点间游走。如 使用xpath,则能提供更强大的查询能力。
有必要介绍几个常用类所表达的概念。
Node:最抽象的接口。表示一个结点。它的含义很广泛。整个xml树是一个结点,一个完整的标签也是结点,一个属性也是结点,一段文本也是结点,一个注释也是结点,一个预处理指令也是结点等。节点可以包含:名字、值、属性等。但并非每种特殊的结点都有这些性质。
Document:接口。继承了Node。表示整个xml文档树。它有几个子结点?1个。这是xml定义所约定的。Document结点并不是xml的根 结点,它比根结点还高一层。它的结点名字是 "#document",这个在xml文件中看不到,是为了分析方便这样规定的。
Element:接口。继承了Node。表示一个标签元素。它可能有属性集合。它可能有许多子结点。它的名字就是标签的名字。但它没有"值"特性。需要特别注意 --!!
Attr:接口。继承了Node。表示一项属性。它的名字就是等号左边的串,值就是等号右边被引号引用的串。
需要注意的概念细节:
如有xml是这样的:<A>aaa<B></B></A>
此时,<A>结点包含几个子结点呢?2个!其中“长子”是文本,“次子”是元素<B>。
如有xml是这样的:
<A>
</A>
<A>结点包含几个子结点呢?1个!是个文本结点,其值是“回车符”。
如xml是这样的:
<作者>张三丰</作者>
假设 Element p = ... 已经指向了<作者>这个结点,如何取得“张三丰”这个串呢?
许多人以为是:p.getNodeValue()。这是典型的概念错误!正确是:p.getFirstChild().getNodeValue()。
千万要记住:<作者>这个Node是个Element,它没有value这个特性!而它唯一的子结点是个Text,它有value特性。
还有些类似的概念问题不再赘述,写一个可运行的Java例程或者更好。
准备一个xml文件,如下,命名为:test.xml:
<?xml version="1.0" encoding="gb2312" ?>
<RRR>
<AAA> </AAA>
<BBB></BBB>
<CCC/>
<DDD>
</DDD>
</RRR>
Java程序如下:
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
public class DomTest
{
public static void main(String[] args) throws Exception
{
// 1. 从文件中读入数据,形成Document对象
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("test.xml"));
System.out.println("Document 有几个孩子? " + dom.getChildNodes().getLength());
System.out.println("根节点是:" + dom.getFirstChild().getNodeName());
// 2. 看根节点的多少孩子
Element root = dom.getDocumentElement();
System.out.println("根节点是:" + root.getNodeName());
System.out.println("<RRR>的子节点数目:" + root.getChildNodes().getLength());
//3. 看<AAA>所含文本
NodeList a = root.getElementsByTagName("AAA");
String s = a.item(0).getFirstChild().getNodeValue();
System.out.println("<AAA>包含的文本是:[" + s + "]");
//3. 看<BBB>所含文本
a = root.getElementsByTagName("BBB");
Node t = a.item(0).getFirstChild();
if(t==null) System.out.println("<BBB>包含的文本是空对象");
//4. 看<CCC>所含文本
a = root.getElementsByTagName("CCC");
t = a.item(0).getFirstChild();
if(t==null) System.out.println("<CCC>包含的文本是空对象");
//5. 看<DDD>所含文本
a = root.getElementsByTagName("DDD");
s = a.item(0).getFirstChild().getNodeValue();
System.out.println("<DDD>包含的文本是:[" + s + "]");
}
}
public interface NodeList 接口
NodeList
接口提供对节点的有序集合的抽象,没有定义或约束如何实现此集合。DOM 中的 NodeList
对象是活动的。
NodeList
中的项可以通过从 0 开始的整数索引进行访问。
方法摘要(只有两个) | |
---|---|
int |
getLength() 列表中的节点数。 |
Node |
item(int index) 返回集合中的第 index 个项。 |
public interface Node
该 Node
接口是整个文档对象模型的主要数据类型。它表示该文档树中的单个节点。当实现 Node
接口的所有对象公开处理子节点的方法时,不是实现 Node
接口的所有对象都有子节点。例如,Text
节点可能没有子节点,且将子节点添加到这样的节点将导致引发 DOMException
。
包括属性 nodeName
、nodeValue
和 attributes
作为一种获取节点信息的机制,无需向下强制转换为特定的派生接口。在没有对特定的 nodeType
(如 Element
的 nodeValue
或 Comment
的 attributes
)的属性的明显映射的情况下,这将返回 null
。注意,特定的接口可能包含其他更方便的机制来获取和设置相关信息。
nodeName
、nodeValue
和 attributes
的值将根据以下节点类型的不同而不同。
Interface | nodeName | nodeValue | attributes |
---|---|---|---|
Attr |
与 Attr.name 相同 |
与 Attr.value 相同 |
null |
CDATASection |
"#cdata-section" |
与 CharacterData.data 相同,CDATA 节的内容 |
null |
Comment |
"#comment" |
与 CharacterData.data 相同,该注释的内容 |
null |
Document |
"#document" |
null |
null |
DocumentFragment |
"#document-fragment" |
null |
null |
DocumentType |
与 DocumentType.name 相同 |
null |
null |
Element |
与 Element.tagName 相同 |
null |
NamedNodeMap |
Entity |
entity name | null |
null |
EntityReference |
引用的实体名称 | null |
null |
Notation |
notation name | null |
null |
ProcessingInstruction |
与 ProcessingInstruction.target 相同 |
与 ProcessingInstruction.data 相同 |
null |
Text |
"#text" |
与 CharacterData.data 相同,该文本节点的内容 |
null |
字段摘要 | |
---|---|
static short |
ATTRIBUTE_NODE 该节点为 Attr 。 |
static short |
DOCUMENT_NODE 该节点为 Document 。 |
static short |
ELEMENT_NODE 该节点为 Element 。 |
static short |
TEXT_NODE 该节点为 Text 节点。 |
方法摘要 | |
---|---|
Node |
appendChild(Node newChild) 将节点 newChild 添加到此节点的子节点列表的末尾。 |
Node |
cloneNode(boolean deep) 返回此节点的副本,即允当节点的一般复制构造方法。 |
Node |
getFirstChild() 此节点的第一个子节点。 |
Node |
getLastChild() 此节点的最后一个子节点。 |
String |
getNodeName() 此节点的名称,取决于其类型;参见上表。 |
short |
getNodeType() 表示基础对象的类型的节点,如上所述。 |
String |
getNodeValue() 此节点的值,取决于其类型;参见上表。 |
Document |
getOwnerDocument() 与此节点相关的 Document 对象。 |
Node |
getParentNode() 此节点的父节点。 |
void |
setTextContent(String textContent) 此属性返回此节点及其后代?的文本内容。 |
String |
getTextContent() 此属性返回此节点及其后代?的文本内容。 |
public interface Element
extends Node
Element
接口表示 HTML 或 XML 文档中的一个元素。元素可能有与它们相关的属性;由于 Element
接口继承自 Node
,所以可以使用一般 Node
接口属性 attributes
来获得元素所有属性的集合。Element
接口上有通过名称获得 Attr
对象或通过名称获得属性值的方法。在 XML 中(其中的属性值可能包含实体引用),应该获得 Attr
对象来检查表示属性值的可能相当复杂的子树。另一方面,在 HTML 中(其中的所有属性都有简单的字符串值),可以使用直接访问属性值的方法,这既安全又便捷。
方法摘要 | |
---|---|
String |
getAttribute(String name) 通过名称获得属性值。 |
Attr |
getAttributeNode(String name) 通过名称获得属性节点。 |
NodeList |
getElementsByTagName(String name) 以文档顺序返回具有给定标记名称的所有后代 Elements 的 NodeList 。 |
NodeList |
getElementsByTagNameNS(String namespaceURI, String localName) 以文档顺序返回具有给定本地名称和名称空间 URI 的所有后代 Elements 的 NodeList 。 |
TypeInfo |
getSchemaTypeInfo() 与此元素相关的类型信息。 |
String |
getTagName() 元素的名称。 |
boolean |
hasAttribute(String name) 当具有给定名称的属性在此元素上被指定一个值或具有默认值时,返回 true ;否则返回 false 。 |
void |
setAttributeNS(String namespaceURI, String qualifiedName, String value) 添加新属性。 |
void |
setAttribute(String name, String value) 添加一个新属性。 |
从接口 org.w3c.dom.Node 继承的方法 |
---|
appendChild, cloneNode, compareDocumentPosition, getAttributes, getBaseURI, getChildNodes, getFeature, getFirstChild, getLastChild, getLocalName, getNamespaceURI, getNextSibling, getNodeName, getNodeType, getNodeValue, getOwnerDocument, getParentNode, getPrefix, getPreviousSibling, getTextContent, getUserData, hasAttributes, hasChildNodes, insertBefore, isDefaultNamespace, isEqualNode, isSameNode, isSupported, lookupNamespaceURI, lookupPrefix, normalize, removeChild, replaceChild, setNodeValue, setPrefix, setTextContent, setUserData |