[XML]学习笔记(九)DOM

DOM是一个使程序和脚本有能力动态的访问和更新文档的内容、结构以及样式的平台和语言中立的接口,主要被分为三个不同的部分:核心DOM、XML DOM和HTML DOM。http://www.w3school.com.cn/xmldom/dom_intro.asp

一、JAXP接口(Java API for XMLParsing)

a)        org.w3c.dom W3C推荐的用于XML标准规划文档对象模型的接口。

b)        org.xml.sax 用于对XML进行语法分析的事件驱动的XML简单API(SAX)。

c)        javax.xml.parsers解析器工厂工具,程序员获得并配置特殊的特殊语法分析器。

二、这三个包在jdk中都有

三、XML DOM的主要用途:

XML DOM(Document Object Model)即XML文档对象模型,它定义了访问和处理XML文档的标准方法,或者说XML DOM是用于获取、更改、添加或删除XML元素的标准。

主要应用于:

1)        在需要修改XML文档的内容、结构和顺序时;

2)        需要多次遍历XML文档时;

3)        归并多个XML文档时;

4)        对XML内容做复杂操作。

DOM的工作流程:

DOM解析器将整篇的XML文档加载到内存中,并以树的形式保存,含有丰富的API,所有对象在DOM中都被看作是Node/节点。

四、XML DOM解析的基本步骤:

a)        应用程序生成DOM解析器

b)        解析器加载XML

c)        解析器向应用程序返回错误信息

d)        解析器生成DOM树

e)        应用程序读写DOM树

f)         应用程序将DOM树转化为XML文档输出

五、DOM树:

a)        抽象的:

b)        真实的:

六、XML DOM常用节点

DOM规定,XML文档中的每个成分都是一个节点

a)        Document——整个文档为一个文档节点documentElement,代表整个文档,只有一个元素子节点root,但可以有多个其它类型的子节点;

而DocumentFragment表示一个XML片段,用于修改DOM树、截取与合并XML片段。

b)        Element——每个XML标签为一个元素节点;

c)        Text——包含在XML元素中的文本是文本节点;注意文本总是存储在文本节点中,元素节点不包含文本,元素节点的文本也是存储在文本节点中的,如<name>CHZH<name>,CHZH不是name的值,而是name拥有一个值为CHZH的文本节点。

d)        Attr——每个XML属性是一个属性节点,注意属性节点和元素节点不存在父子关系;

e)        注释属于注释节点。

七、解析XML DOM

f)         如下面的JavaScript片段将books.xml载入了解析器:

xmlDoc=newActiveXObject("Microsoft.XMLDOM"); #创建空的微软XML文档对象

<!--xmlDoc=document.implementation.createDocument("","",null)  --> #创建Firefox或其他浏览器中的空的XML文档对象

xmlDoc.async="false";#关闭异步加载,确保在文档加载完整前解析器不会继续执行脚本

xmlDoc.load("books.xml");#加载books.xml

load()用于加载文件,而loadXML()用于加载字符串/文本。

一个跨浏览器解析XML文档的实例:

<html>
<body>
<script type="text/javascript">
try //IE
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    xmlDoc=document.implementation.createDocument("","",null);
    }
  catch(e) {alert(e.message)}
  }
try 
  {
  xmlDoc.async=false;
  xmlDoc.load("books.xml");
  document.write("xmlDoc is loaded, ready for use");
  }
catch(e) {alert(e.message)}
</script>
</body>
</html>

g)        如下面的JavaScript片段把名为txt的字符串载入解析器:

parser=new DOMParser(); #创建一个空的XML文档对象
xmlDoc=parser.parseFromString(txt,"text/xml"); #告知解析器加载名为txt的字符串

IE使用loadXML()解析XML字符串,方法同上面解析XML文档的方法,需要创建xmlDoc文档对象,并且需要关闭异步加载;而其他浏览器使用DOMParser()对象。

一个跨浏览器解析XML字符串的例子:

<html>
<body>
<script type="text/javascript">
text="<bookstore>"
text=text+"<book>";
text=text+"<title>Harry Potter</title>";
text=text+"<author>J K. Rowling</author>";
text=text+"<year>2005</year>";
text=text+"</book>";
text=text+"</bookstore>";
 
try //IE
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async="false";
  xmlDoc.loadXML(text);
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    parser=new DOMParser();
    xmlDoc=parser.parseFromString(text,"text/xml");
    }
  catch(e) {alert(e.message)}
  }
document.write("xmlDoc is loaded, ready for use");
</script>
</body>
</html>

八、XML DOM加载函数

为了避免编写重复的代码,将一些代码存储在函数中,并可以使用XML DOM加载。如上面的加载XML文档代码可定义为loadXMLDoc(dname)函数,存储在"loadxmldoc.js"文件中:

function loadXMLDoc(dname) 
{
try //Internet Explorer
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    xmlDoc=document.implementation.createDocument("","",null);
    }
  catch(e) {alert(e.message)}
  }
try 
  {
  xmlDoc.async=false;
  xmlDoc.load(dname);
  return(xmlDoc);
  }
catch(e) {alert(e.message)}
return(null);
}

在使用过程中,可以直接引用该函数:

<html>
<head>
<script type="text/javascript" src="loadxmldoc.js"> #先创建一个指向该函数存储文件链接
</script>
</head>
 
<body>
<script type="text/javascript">
xmlDoc=loadXMLDoc("books.xml"); #加载books.xml文档
document.write("xmlDoc is loaded, ready for use");
</script>
</body>
</html>

九、 XML DOM属性和方法:设x为一个节点对象

h) 常用的属性:

i. x.nodeName:x的名称;

ii. x.nodeValue:x的文本值;

iii. x.parentNode:x的父节点;

iv. x.childNodes:x的子节点;

v. x.attributes:x的属性节点。

i) 常用的方法:

i. x.getElementsByTagName(name):获取标签名称为name的所有元素;

ii. x.appendChild(node):向x插入子节点node

iii. x.removeChild(node):从x删除子节点node

如源books.xml为:

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<bookstore>
 
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>
 
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
 
<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>
 
<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>
 
</bookstore>

通过java程序testDOM.java来对books.xml进行访问:

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class testDOM {
         public static void main(String[] args) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        File f = new File("books.xml");
        Document doc = builder.parse(f);
        Element root = doc.getDocumentElement();
        NodeList list = root.getElementsByTagName("book");
         
        for (int i = 0; i < list.getLength(); i++) {
            Element n = (Element) list.item(i);
            NamedNodeMap node = n.getAttributes();
            for (int x = 0; x < node.getLength(); x++) {
                Node nn = node.item(x);
                System.out.println(nn.getNodeName() + ": " + nn.getNodeValue());
            }
            System.out.println("title: " +n.getElementsByTagName("title").item(0).getFirstChild().getNodeValue());
            System.out.println("author: " + n.getElementsByTagName("author").item(0).getFirstChild().getNodeValue());
            System.out.println();
        }
    }
}

得到的结果为:

category:COOKING

title: EverydayItalian

author: Giada DeLaurentiis

category:CHILDREN

title: HarryPotter

author: J K.Rowling

category: WEB

title: XQueryKick Start

author: JamesMcGovern

category: WEB

title: LearningXML

author: Erik T.Ray

十、XML DOM访问节点的三种方式:

j)          通过x.getElementByTagName(name)指定节点标签名的方式访问,注意该访问方式为x下所有含有<name>标签的元素,如需访问整个文档中所有的<name>元素,则使用xmlDoc.getElementByTagName(name);该方式获得的结果为一个节点列表(NodeList),可以通过下标访问,如x[0]。

k)        通过遍历节点树的方式访问,如在java中是通过getLength()获取当前NodeList的节点数,然后使用NodeList.item(i)的方式访问,其中i为从0起始的下标;

x=xmlDoc.documentElement.childNodes;
for (i=0;i<x.length;i++)
{ 
if (x[i].nodeType==1)
  {//Process only element nodes (type 1) 
  document.write(x[i].nodeName);
  document.write("<br />");
  }
}

l)          通过节点关系进行访问,如

         x=xmlDoc.getElementsByTagName("book")[0].childNodes;
         y=xmlDoc.getElementsByTagName("book")[0].firstChild;

十一、      XML DOM获取节点信息:

a) nodeName:规定节点的名称:

i. nodeName是只读的;

ii. 元素节点的nodeName即标签名;

iii. 属性节点的nodeName即属性名;

iv. 文本节点的nodeName即#text;

v. 文档节点的nodeName即#document。

b) nodeValue:规定节点的值:

i. nodeValue可修改,可以通过直接的赋值语句更改;

ii. 元素节点的nodeValue为undefined;

iii. 属性节点的nodeValue为属性值;

iv. 本文节点的nodeValue为文本内容;

c) nodeType:规定节点的类型,只读。


元素类型


节点类型


元素


1


属性


2


文本


3


注释


8


文档


9

十二、      Node List节点列表

a) Node List对象会保持更新,每当添加或删除元素后,列表信息都会被更新;

b) 获得属性列表Attribute List:如xmlDoc.getElementsByTagName(‘book‘)[0].attributes,与节点列表相同,会保持更新。

十三、      DOM中的空白与换行

XML 经常在节点之间含有换行或空白字符,Firefox以及其他一些浏览器,会把空白或换行作为文本节点来处理,而 Internet Explorer则不会。

如果需要忽略元素节点之间的空文本节点,则需要进行节点类型检查,只对于nodeType为1的节点进行处理。

functionget_nextSibling(n)

{

y=n.nextSibling;

while (y.nodeType!=1)

{

y=y.nextSibling;

}

return y;

}

十四、      XML DOM节点值操作:

a) 元素节点操作:

i. 获取:nodeValue属性用于获取节点的文本节点(一般也将文本节点称为该节点的子节点)的值;

ii. 修改:可以通过为nodeValue直接赋值进行更改值操作。

iii. 删除:可以通过parentNode.removeChild(childNode)来删除parentNode下的childNode节点,删除一个节点后其所有的子节点都会被删除。removeChild()同样可以用来删除文本节点,当然,对文本节点直接赋值为""也可得到删除的效果。

iv. 替换:x.replaceChild(origNode, newNode),其中x为文档的根节点xmlDoc.documentElement。

v. 创建:xmlDoc.createElement(nodeName),创建一个名为nodeName的节点。

vi. 添加:parentNode.appendChild(childNode) 方法向已存在的节点添加子节点。parentNode.insertBefore(newChildNode,selectedNode) 方法用于在parentNode的子节点selectedNode之前插入节点newChildNode,如果子节点参数为null,则插到最后一个子节点后面,与appendChild()功能相同。

vii. 克隆:newNode=oldNode.cloneNode(true|false),true和false表示新的节点是否克隆源节点的所有属性和子节点。

如:

xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0];
y=x.childNodes[0];#y为第一个title的文本节点
txt=x.nodeValue; #txt为文本元素
x.removeChild(y);

b) 属性节点操作:

i. 获取:getAttribute()方法返回属性的值。

ii. 修改:setAttribute(attrName, newValue)方法用于设置属性的值,如果attrName不存在,则创建一个attrName属性,并将值赋为newValue。当然,也可以在获取属性节点后直接通过nodeValue进行赋值操作修改其值。

iii. 删除:removeAttribute(attrName)可以用于删除指定的属性。

iv. 创建:xmlDoc.createAttribute(attrName),创建一个名为attrName的属性,设为newAttr,然后可以通过newAttr.nodeValue设置属性值。通过对于某个元素节点x可以通过x.setAttributeNode(newAttr)的方式添加属性。除此之外,利用setAttribute()可以直接创建没有出现过的属性。

v. 添加:通过x.setAttributeNode(newAttr)的方式添加属性。

如:

xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0].getAttributeNode("lang");
txt=x.nodeValue;

c) 文本节点操作:

vi. 创建:xmlDoc.createTextNode(textValue),创建一个值为textValue的文本节点。

vii. 替换:x.replaceData(offset, length, string),x为文本节点,其中offset表示从何处开始替换,以0开始;length表示被替换的字符个数;string表示新的要插入的字符串。当然,通过nodeValue也可以完成替换操作。

viii. 添加:x.insertData(offset, string),x为文本节点,其中offset表示从何处添加,以0开始;string表示新的要插入的字符串。

d) CDATA Section节点操作:

ix. 创建:xmlDoc.createCDATASection(CDATAValue),创建一个值为CDATAValue的CDATA Section节点。

e) 注释节点操作:

x. 创建:xmlDoc.createComment(commentValue),创建一个值为commentValue的注释节点。

十五、      XML DOM解析器的生成(四步):

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();#生成实例,工厂模式类似于new,但比new灵活,见http://blog.csdn.net/cristianojason/article/details/51510093
Factory.setValidating(false);#设定解析选项
DocumentBuilder builder = factory.newDocumentBuilder();#从factory中生成builder
Document doc = builder.parse(xmlFileURL);#解析文档

XMLDOM遍历解析树:

 Element root = doc.getDocumentElement();#获得root实例
NodeList children = root.getChildNodes();#获得所有节点

十六、      构造新的DOM树(五步):

Document newDoc = DocumentBuilder.newDocument();#定义新的Document
Element newRoot = newDoc.createElement(“rootName”);#建立新的根节点newRoot
#第三步自顶向下的构建分支
#第四步插入分支
newDoc.appendChild(newRoot)#第五步将newRoot插入到newDoc

十七、      XML DOM进行文档归并:

a)        解析两个文档;

b)        import被归并文档;

c)        将被归并文档的节点插入目标文档的适当位置;

如:

Document doc1 = builder.parse(xmlFileURL1);
Document doc2 = builder.parse(xmlFileURL2);
Element root1 = doc1.getDocumentElement();
Element root2 = doc2.getDocumentElement();
NodeList children = root1.getChildNodes();
for(int i = 0; i < children.getLength(); i++) {
     Element newChild = (Element)children.item(i);
     Node newImportedChild = doc1.importNode(newChild, true);
     root1.appendChild(newImportedChild);
}

十八、      DOM应用程序:

a)  生成解析器(四步)

i. 定义factory

ii. 配置解析器

iii.生成解析器

iv. 解析文档

b)  处理错误和异常

c)  遍历DOM树

d)  处理文档

i. 修改内容

ii. 修改结构

iii. 移动节点

时间: 2024-07-30 10:14:30

[XML]学习笔记(九)DOM的相关文章

XML学习笔记(五):使用 jdom和dom4j 解析XML

XML解析的详细分析与jaxp解析XML详见:XML学习笔记(四):使用 DOM和SAX 解析XML 一.JDom 1.创建XML文件: 1)Document类即代表整个XML文档,把生成的 Document 利用 XMLOutputter 类输出即可. 2)映射关系:元素:Element:属性:Attribute:注解:Comment:文本信息:Text: 3)注意:addContent()是追加,setContent()会覆盖. /** * 创建XML * * @throws IOExcep

xml学习笔记(1)

xml 学习笔记 XML : W3C 提供的可拓展的HTMl标签 作用 : 存储,配置 数据存储在XMl中,写好XML文件后要用程序去读取其中的数据,而读取程序的过程叫做解析. xml 的解析方式分为两种: dom (Document Objecct Model 文档对象模型) W3C组织推荐的解析模式 Sax (Simple API for Xml )是xml社区事实上的标准 ,几乎所有的XML解析器都支持它 XML 解析器: Crimson(sun ) Xerces(IBM) Aelfred

《Hibernate学习笔记九》:多对一和一对多的关联关系

<Hibernate学习笔记九>:多对一和一对多的关联关系 前面介绍了一对一的关联关系在Hibernate应该如何来实现,这篇博文就来介绍下多对一和一对多的关联关系. 多对一和一对多的关联关系在我们的生活中也比较常见,例如,在我们学生时代,一个班级可以有多个学生,而一个学生只能属于一个班级,这就是一个多对一(一对多)的例子: 还有在我们的工作中,一个工作小组可以有多个用户,而一个用户只能属于一个小组,这也是一个多对一(一对多)的关系的例子. 1.多对一的单向关联关系 下面就以一个工作小组可以有

APUE 学习笔记(九) 高级I/O

1. 非阻塞I/O 低速系统调用时可能会使进程永远阻塞的一类系统调用,包括以下调用: (1)某些文件类型你(网络socket套接字.终端设备.管道)暂无可使用数据,则读操作可能会使调用者永远阻塞 (2)如果数据不能立即被(1)中文件类型接受,则写操作会使调用者永远阻塞 (3)某些进程间通信函数 非阻塞I/O使我们可以调用open.read.write这样的I/O操作,并使这些操作不会永远阻塞,如果这种操作不能完成,则调用立即出错返回 对于一个给定的文件有两种方法对其指定非阻塞I/O: (1)调用

dojo 学习笔记之一 dom.byId dojo.byId registry.byId 的区别

在dojo中,除了沿用Dom结点, dojo 还自定义了一类结点用"dojoType" 进行标识. dojo 称这些结点为widget. 当检测到HTMl文档中某个标签定义了dojoType 属性之后,dojo会调用dojo包中相应的 js 及 css 文件对这个结点进行渲染. 从而这个结点元素就会相应地显示出具有dojo特色的样式及功能. 如此说来, dom.byId 跟 dojo.byId 获取到的就是普通的HTMl文档结构树中的某个结点元素,以下简称dom结点, 而 regist

python学习笔记九——文件与目录

1.python进行文件读写的函数是open或file类 mode:r  只读 r+   读写 w  写入,先删除原文件,再重新写入,如果文件没有则创建 w+  读写,先删除原文件,再重新写入,如果文件没有则创建(可写入和输出) a  写入,在文件末尾追加新的内容,文件不存在则创建 a+  读写,在文件末尾追加新的内容,文件不存在则创建 b  打开二进制文件,可与r,w,a,+结合使用 U  支持所有的换行符号,"\r","\n","\r\n"

angular学习笔记(九)-css类和样式3

再来看一个选择li列表的例子: 点击li中的任意项,被点击的li高亮显示: <!DOCTYPE html> <html ng-app> <head> <title>6.3css类和样式</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script src="scri

angular学习笔记(九)-css类和样式2

在上一个例子中,元素的类名使用拼接的方法,这样,类名中就不得不带有true或false,并且不易维护,所以,angular使用ng-class属性来控制元素的类名: 我们来看一个小例子,点击error按钮,顶部提示错误框,点击warning按钮,顶部提示警告框. 错误框的类名是.err,警告框的类名是.warn: <!DOCTYPE html> <html ng-app> <head> <title>6.2css类和样式</title> <

Linux System Programming 学习笔记(九) 内存管理

1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系结构决定了内存页大小,32位系统通常是 4KB, 64位系统通常是 8KB 内存页分为 valid or invalid: A valid page is associated with an actual page of data,例如RAM或者磁盘上的文件 An invalid page is

XML学习笔记之:XSLT &lt;xsl:variable&gt; 元素

声明:该笔记引自W3School! 1.<xsl:variable> 元素用于声明局部或全局的变量. 2.可以通过 <xsl:variable> 元素的内容或通过 select 属性,向变量添加值! 3.一旦设置了变量的值,就无法改变或修改该值! <xsl:variable name="name" select="expression"> <!-- Content:template --> </xsl:varia