XML DOM

DOM简介

XML DOM 定义了访问和处理 XML 文档的标准。

您应当具备的基础知识

在继续学习之前,您应当对下列知识有基本的了解:

  • HTML
  • XML
  • JavaScript

DOM 定义了访问诸如 XML 和 HTML 文档的标准:

"W3C 文档对象模型(DOM,全称 Document Object Model)是一个使程序和脚本有能力动态地访问和更新文档的内容、结构以及样式的平台和语言中立的接口。"

DOM 被分为 3 个不同的部分/级别:

  • 核心 DOM - 用于任何结构化文档的标准模型
  • XML DOM - 用于 XML 文档的标准模型
  • HTML DOM - 用于 HTML 文档的标准模型

DOM 定义了所有文档元素的对象和属性,以及访问它们的方法(接口)。

换句话说:XML DOM 是用于获取、更改、添加或删除 XML 元素的标准。

DOM 节点

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

DOM 是这样规定的:

  • 整个文档是一个文档节点
  • 每个 XML 元素是一个元素节点
  • 包含在 XML 元素中的文本是文本节点
  • 每一个 XML 属性是一个属性节点
  • 注释是注释节点

文本总是存储在文本节点中

在 DOM 处理中一个普遍的错误是,认为元素节点包含文本。

不过,元素节点的文本是存储在文本节点中的。

在这个实例中:<year>2005</year>,元素节点 <year>,拥有一个值为 "2005" 的文本节点。

"2005" 不是 <year> 元素的值!

XML DOM 节点树

XML DOM 把 XML 文档视为一种树结构。这种树结构被称为节点树

可通过这棵树访问所有节点。可以修改或删除它们的内容,也可以创建新的元素。

这颗节点树展示了节点的集合,以及它们之间的联系。这棵树从根节点开始,然后在树的最低层级向文本节点长出枝条:

 

父节点、子节点和同级节点

节点树中的节点彼此之间都有层级关系。

父节点、子节点和同级节点用于描述这种关系。父节点拥有子节点,位于相同层级上的子节点称为同级节点(兄弟或姐妹)。

  • 在节点树中,顶端的节点称为根节点
  • 根节点之外的每个节点都有一个父节点
  • 节点可以有任何数量的子节点
  • 叶子是没有子节点的节点
  • 同级节点是拥有相同父节点的节点

下面的图片展示出节点树的一个部分,以及节点间的关系:

XML DOM 解析器

XML DOM 包含了遍历 XML 树,访问、插入及删除节点的方法(函数)。

然而,在访问和操作 XML 文档之前,它必须加载到 XML DOM 对象。

XML 解析器读取 XML,并把它转换为 XML DOM 对象,这样才可以使用 JavaScript 访问它。

大多数浏览器有一个内建的 XML 解析器。

加载 XML 文档

下面的 JavaScript 片段加载一个 XML 文档("books.xml"):

if (window.XMLHttpRequest)
{
  // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
  xhttp=new XMLHttpRequest();
}
else
{
  // IE6, IE5 浏览器执行代码
  xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET","books.xml",false);
xhttp.send();
xmlDoc=xhttp.responseXML;

代码解释:

  • 创建一个 XMLHTTP 对象
  • 打开 XMLHTTP 对象
  • 发送一个 XML HTTP 请求到服务器
  • 设置响应为 XML DOM 对象

加载 XML 字符串

下面的代码加载并解析一个 XML 字符串:

if (window.DOMParser)
{
  parser=new DOMParser();
  xmlDoc=parser.parseFromString(text,"text/xml");
}
else
{
   // Internet Explorer
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async=false;
  xmlDoc.loadXML(text); 
}

注意:Internet Explorer 使用 loadXML() 方法来解析 XML 字符串,而其他浏览器使用 DOMParser 对象。

跨域访问

出于安全原因,现代的浏览器不允许跨域访问。

这意味着,网页以及 XML 文件,它必须位于同一台服务器上尝试加载。

如果您想要在您的网页上使用上面的实例,您加载的 XML 文件必须位于您自己的服务器上。

编程接口

DOM 把 XML 模拟为一系列节点对象。可通过 JavaScript 或其他编程语言来访问节点。在本教程中,我们使用 JavaScript。

对 DOM 的编程接口是通过一套标准的属性和方法来定义的。

属性经常按照"某事物是什么"的方式来使用(例如节点名是 "book")。

方法经常按照"对某事物做什么"的方式来使用(例如删除 "book" 节点)。

XML DOM 属性

一些典型的 DOM 属性:

  • x.nodeName - x 的名称
  • x.nodeValue - x 的值
  • x.parentNode - x 的父节点
  • x.childNodes - x 的子节点
  • x.attributes - x 的属性节点

注释:在上面的列表中,x 是一个节点对象。

XML DOM 方法

  • x.getElementsByTagName(name) - 获取带有指定标签名称的所有元素
  • x.appendChild(node) - 向 x 插入子节点
  • x.removeChild(node) - 从 x 删除子节点

注释:在上面的列表中,x 是一个节点对象。

实例 1

从 books.xml 中的 <title> 元素获取文本的 JavaScript 代码:

txt=xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue

在该语句执行后,txt 保存的值是 "Everyday Italian"。

解释:

  • xmlDoc - 由解析器创建的 XML DOM 对象
  • getElementsByTagName("title")[0] - 第一个 <title> 元素
  • childNodes[0] - <title> 元素的第一个子节点(文本节点)
  • nodeValue - 节点的值(文本本身)

XML DOM - 访问节点

通过 DOM,您能够访问 XML 文档中的每个节点。

访问节点

您可以通过三种方式来访问节点:

1. 通过使用 getElementsByTagName() 方法。

2. 通过循环(遍历)节点树。

3. 通过利用节点的关系在节点树中导航。

getElementsByTagName() 方法

getElementsByTagName() 返回拥有指定标签名的所有元素。

node.getElementsByTagName("tagname");

 下面的实例返回 x 元素下的所有 <title> 元素:

x.getElementsByTagName("title");

 请注意,上面的实例仅返回 x 节点下的 <title> 元素。如需返回 XML 文档中的所有 <title> 元素,请使用:

xmlDoc.getElementsByTagName("title");

在这里,xmlDoc 就是文档本身(文档节点)。

DOM 节点列表(Node List)

getElementsByTagName() 方法返回节点列表。节点列表是节点的数组。

下面的代码使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中,然后在变量 x 中存储 <title> 节点的一个列表:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title");

 可通过索引号访问 x 中的 <title> 元素。如需访问第三个 <title>,您可以编写:

y=x[2];

注意:该索引从 0 开始。

DOM 节点列表长度(Node List Length)

length 属性定义节点列表的长度(即节点的数量)。

您可以通过使用 length 属性来遍历节点列表:

xmlDoc=loadXMLDoc("books.xml"); //使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
 
x=xmlDoc.getElementsByTagName("title"); //获取所有 <title> 元素节点
 
for (i=0;i<x.length;i++)
{
  document.write(x[i].childNodes[0].nodeValue); //输出每个 <title> 元素的文本节点的值
  document.write("");
}

节点类型(Node Types)

XML 文档的 documentElement 属性是根节点。

节点的 nodeName 属性是节点的名称。

节点的 nodeType 属性是节点的类型。

下面的代码遍历根节点的子节点,同时也是元素节点: 

xmlDoc=loadXMLDoc("books.xml"); //使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
 
x=xmlDoc.documentElement.childNodes; //获取根元素的子节点
 
for (i=0;i<x.length;i++)
{
  if (x[i].nodeType==1)  //检查每个子节点的节点类型。如果节点类型是 "1",则是元素节点
  {
    // 如果是元素节点,则输出节点的名称
    document.write(x[i].nodeName); 
    document.write("");
  }
}

导航节点的关系

下面的代码使用节点关系导航节点树:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.getElementsByTagName("book")[0].childNodes;
y=xmlDoc.getElementsByTagName("book")[0].firstChild;
 
for (i=0;i<x.length;i++)
{
  if (y.nodeType==1)
  {
  // 输出节点名
  document.write(y.nodeName + "");
  }
  y=y.nextSibling;
}
  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取第一个 book 元素的子节点
  3. 把 "y" 变量设置为第一个 book 元素的第一个子节点
  4. 对于每个子节点(第一个子节点从 "y" 开始),检查节点类型,如果节点类型为 "1",则是元素节点
  5. 如果是元素节点,则输出该节点的名称
  6. 把 "y" 变量设置为下一个同级节点,并再次运行循环

XML DOM 节点信息 

nodeName、nodeValue 和 nodeType 属性包含有关节点的信息。 

节点的属性

在 XML DOM 中,每个节点都是一个对象

对象拥有方法和属性,并可通过 JavaScript 进行访问和操作。

三个重要的节点属性是:

  • nodeName
  • nodeValue
  • nodeType

nodeName 属性

nodeName 属性规定节点的名称

  • nodeName 是只读的
  • 元素节点的 nodeName 与标签名相同
  • 属性节点的 nodeName 是属性的名称
  • 文本节点的 nodeName 永远是 #text
  • 文档节点的 nodeName 永远是 #document

nodeValue 属性

nodeValue 属性规定节点的值

  • 元素节点的 nodeValue 是 undefined
  • 文本节点的 nodeValue 是文本本身
  • 属性节点的 nodeValue 是属性的值

获取元素的值

下面的代码检索第一个 <title> 元素的文本节点的值:

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

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取第一个 <title> 元素节点的文本节点
  3. 把 txt 变量设置为文本节点的值

更改元素的值

下面的代码更改第一个 <title> 元素的文本节点的值:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Easy Cooking"; //更改文本节点的值为 "Easy Cooking"

nodeType 属性

nodeType 属性规定节点的类型。

nodeType 是只读的。

最重要的节点类型是:

节点类型NodeType
元素1
属性2
文本3
注释8
文档9

DOM 节点列表


节点列表由 getElementsByTagName() 方法和 childNodes 属性返回。

DOM 节点列表(Node List)

当使用诸如 childNodes 或 getElementsByTagName() 的属性或方法时,会返回节点列表对象。

节点列表对象表示节点的列表,与 XML 中的顺序相同。

节点列表中的节点使用从 0 开始的索引号进行访问。

下面的图像表示 "books.xml" 中 <title> 元素的节点列表:

下面的代码片段通过使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中,并返回 "books.xml" 中 title 元素的节点列表: 

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title");

在上面的语句执行之后,x 是节点列表对象。

下面的代码片段从节点列表(x)中的第一个 <title> 元素返回文本:

txt=x[0].childNodes[0].nodeValue;

节点列表长度(Node List Length)

节点列表对象会保持自身的更新。如果删除或添加了元素,列表会自动更新。

节点列表的 length 属性是列表中节点的数量。

下面的代码片段通过使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中,并返回 "books.xml" 中 <title> 元素的数量:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName('title').length;

在上面的语句执行之后,x = 4。

节点列表的长度可用于遍历列表中所有的元素。

下面的代码片段使用 length 属性来遍历 <title> 元素的列表:

xmlDoc=loadXMLDoc("books.xml");
 
// x 变量获取指定节点列表
x=xmlDoc.getElementsByTagName('title');
 
for (i=0;i<x.length;i++)
{
  document.write(x[i].childNodes[0].nodeValue); //从所有 <title> 元素的文本节点输出值
  document.write("");
}

DOM 属性列表(命名节点图 Named Node Map)

元素节点的 attributes 属性返回属性节点的列表。

这被称为命名节点图(Named Node Map),除了方法和属性上的一些差别以外,它与节点列表相似。

属性列表会保持自身的更新。如果删除或添加属性,这个列表会自动更新。

下面的代码片段通过使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中,并返回 "books.xml" 中第一个 <book> 元素的属性节点列表:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName('book')[0].attributes;

在上面的代码执行之后,x.length 等于属性的数量,可使用 x.getNamedItem() 返回属性节点。

下面的代码片段显示一个 book 的 "category" 属性的值,以及其属性的数量:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.getElementsByTagName("book")[0].attributes;
 
document.write(x.getNamedItem("category").nodeValue);
document.write("" + x.length);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 设置 x 变量来保存第一个 <book> 元素的所有属性的一个列表
  3. 从 "category" 属性输出值
  4. 输出属性列表的长度

DOM 遍历

遍历(Traverse)意味着在节点树中进行循环或移动。


遍历节点树

通常您想要循环 XML 文档,比如:当您需要提取每个元素的值时。

这叫做"遍历节点树"。

下面的实例遍历 <book> 的所有子节点,并显示他们的名称和值:

<!DOCTYPE html>
<html>
<body>
 
<p id="demo"></p>
 
<script>
var x, i ,xmlDoc;
var txt = "";
var text = "<book>" + 
"<title>Everyday Italian</title>" +
"<author>Giada De Laurentiis</author>" +
"<year>2005</year>" +
"</book>";
 
parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"text/xml");
 
// documentElement 表示根节点
x = xmlDoc.documentElement.childNodes;
for (i = 0; i < x.length ;i++) {
    txt += x[i].nodeName + ": " + x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("demo").innerHTML = txt;
</script>
 
</body>
</html>

输出结果:

title: Everyday Italian
author: Giada De Laurentiis
year: 2005

实例解释:

  1. 将 XML 字符串载入 xmlDoc 中
  2. 获取根元素的子节点
  3. 输出每个子节点的节点名称以及文本节点的节点值

DOM 浏览器差异 

DOM 解析中的浏览器差异

所有现代的浏览器都支持 W3C DOM 规范。

然而,浏览器之间是有差异的。一个重要的差异是:

  • 处理空白和换行的方式

DOM - 空白和换行

XML 经常在节点之间包含换行或空白字符。这是在使用简单的编辑器(比如记事本)编辑文档时经常出现的情况。

下面的例子(由记事本编辑)在每行之间包含 CR/LF(换行),在每个子节点之前包含两个空格:

<book>
<title>Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>

Internet Explorer 将不会把空的空白或换行作为文本节点,而其他浏览器会。

下面的代码片段显示(books.xml 的)根元素拥有多少个子节点:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.documentElement.childNodes;
document.write("Number of child nodes: " + x.length);
  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取根元素的子节点
  3. 输出子节点的数量。结果取决于您所使用的浏览器。IE 浏览器会输出 4(提醒 4 个子节点),而其他浏览器会输出 9(提醒 9 个子节点)。

DOM - 导航节点 

可通过使用节点间的关系对节点进行导航。


导航 DOM 节点

通过节点间的关系访问节点树中的节点,通常称为导航节点("navigating nodes")。

在 XML DOM 中,节点的关系被定义为节点的属性:

  • parentNode
  • childNodes
  • firstChild
  • lastChild
  • nextSibling
  • previousSibling

下面的图像展示了 books.xml 中节点树的一个部分,并说明了节点之间的关系:

DOM - 父节点

所有的节点都仅有一个父节点。下面的代码导航到 <book> 的父节点:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.getElementsByTagName("book")[0];
document.write(x.parentNode.nodeName);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取第一个 <book> 元素
  3. 输出 "x" 的父节点的节点名称

避免空的文本节点

Firefox 以及其他一些浏览器,把空的空白或换行当作文本节点,而 Internet Explorer 不会这么做。

这会在使用以下属性:firstChild、lastChild、nextSibling、previousSibling 时产生一个问题。

为了避免导航到空的文本节点(元素节点之间的空格和换行符),我们使用一个函数来检查节点类型:

function get_nextSibling(n)
{
  y=n.nextSibling;
  while (y.nodeType!=1)
  {
    y=y.nextSibling;
  }
  return y;
}

上面的函数允许您使用 get_nextSibling(node)来代替 node.nextSibling 属性。

代码解释:

元素节点的类型是 1。如果同级节点不是元素节点,就移动到下一个节点,直到找到元素节点为止。通过这个办法,在 Internet Explorer 和 Firefox 中,都可以得到相同的结果。

<html>
<head>
<script src="loadxmldoc.js">
</script>
<script>
// 检测第一个节点是否为元素节点
function get_firstChild(n)
{
  y=n.firstChild;
  while (y.nodeType!=1)
  {
    y=y.nextSibling;
  }
  return y;
}
</script>
</head>
 
<body>
<script>
xmlDoc=loadXMLDoc("books.xml");
 
x=get_firstChild(xmlDoc.getElementsByTagName("book")[0]);
document.write(x.nodeName);
</script>
</body>
</html>

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 在第一个 <book> 元素上使用 get_firstChild 函数,来获取第一个子节点(属于元素节点)
  3. 输出第一个子节点(属于元素节点)的节点名称

DOM 获取节点值 

nodeValue 属性用于获取节点的文本值。

getAttribute() 方法返回属性的值。


获取元素的值

在 DOM 中,每种成分都是节点。元素节点没有文本值。

元素节点的文本存储在子节点中。该节点称为文本节点。

获取元素文本的方法,就是获取这个子节点(文本节点)的值。

获取元素值

getElementsByTagName() 方法返回包含拥有指定标签名的所有元素的节点列表,其中的元素的顺序是它们在源文档中出现的顺序。

下面的代码通过使用 loadXMLDoc() 把 books.xml 载入 xmlDoc 中并检索第一个 <title> 元素:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0];

childNodes 属性返回子节点的列表。<title> 元素只有一个子节点。它是一个文本节点。

下面的代码检索 <title> 元素的文本节点:

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

nodeValue 属性返回文本节点的文本值:

x=xmlDoc.getElementsByTagName("title")[0];
y=x.childNodes[0];
txt=y.nodeValue;

获取属性的值

在 DOM 中,属性也是节点。与元素节点不同,属性节点拥有文本值。

获取属性的值的方法,就是获取它的文本值。

可以通过使用 getAttribute() 方法或属性节点的 nodeValue 属性来完成这个任务。

获取属性值 - getAttribute()

getAttribute() 方法返回属性

下面的代码检索第一个 <title> 元素的 "lang" 属性的文本值:

xmlDoc=loadXMLDoc("books.xml"); //使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中

txt=xmlDoc.getElementsByTagName("title")[0].getAttribute("lang"); //把 txt 变量设置为第一个 title 元素节点的 "lang" 属性的值

获取属性值 - getAttributeNode()

getAttributeNode() 方法返回属性节点

下面代码检索第一个 <title> 元素的 "lang" 属性的文本值:

xmlDoc=loadXMLDoc("books.xml");

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

DOM 改变节点值

nodeValue 属性用于改变节点值。

setAttribute() 方法用于改变属性值。

改变元素的值

在 DOM 中,每种成分都是节点。元素节点没有文本值。

元素节点的文本存储在子节点中。该节点称为文本节点。

改变元素文本的方法,就是改变这个子节点(文本节点)的值。

改变文本节点的值

nodeValue 属性可用于改变文本节点的值。

下面的代码片段改变了第一个 <title> 元素的文本节点值:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Easy Cooking";

改变属性的值

在 DOM 中,属性也是节点。与元素节点不同,属性节点拥有文本值。I

改变属性的值的方法,就是改变它的文本值。

可以通过使用 setAttribute() 方法或属性节点的 nodeValue 属性来完成这个任务。

通过使用 setAttribute() 改变属性

setAttribute() 方法改变已有属性的值,或创建新属性。

下面的代码改变 <book> 元素的 category 属性:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName('book');
x[0].setAttribute("category","food"); //把 "category" 属性的值更改为 "food"

通过使用 nodeValue 改变属性

nodeValue 属性可用于更改属性节点的值:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("book")[0]
y=x.getAttributeNode("category");
y.nodeValue="food"; //把该属性节点的值更改为 "food"

DOM 删除节点


removeChild() 方法删除指定节点。

removeAttribute() 方法删除指定属性。

删除元素节点

removeChild() 方法删除指定的节点。

当一个节点被删除时,其所有子节点也会被删除。

下面的代码片段将从载入的 xml 中删除第一个 <book> 元素:

xmlDoc=loadXMLDoc("books.xml");

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

xmlDoc.documentElement.removeChild(y);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 把变量 y 设置为要删除的元素节点
  3. 通过使用 removeChild() 方法从父节点删除元素节点

删除自身 - 删除当前的节点

removeChild() 方法是唯一可以删除指定节点的方法。

当您已导航到需要删除的节点时,就可以通过使用 parentNode 属性和 removeChild() 方法来删除此节点:

xmlDoc=loadXMLDoc("books.xml");

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

x.parentNode.removeChild(x);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 把变量 y 设置为要删除的元素节点
  3. 通过使用 parentNode 属性和 removeChild() 方法来删除此元素节点

删除文本节点

removeChild() 方法可用于删除文本节点:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0];

y=x.childNodes[0];
x.removeChild(y);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 把变量 x 设置为第一个 title 元素节点
  3. 把变量 y 设置为要删除的文本节点
  4. 通过使用 removeChild() 方法从父节点删除元素节点

不太常用 removeChild() 从节点删除文本。可以使用 nodeValue 属性代替它。请看下一段。

清空文本节点

nodeValue 属性可用于改变或清空文本节点的值:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="";

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 把变量 x 设置为第一个 title 元素的文本节点
  3. 使用 nodeValue 属性来清空文本节点的文本

根据名称删除属性节点

removeAttribute(name) 方法用于根据名称删除属性节点。

实例:removeAttribute('category')

下面的代码片段删除第一个 <book> 元素中的 "category" 属性:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("book");
x[0].removeAttribute("category");

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 使用 getElementsByTagName() 来获取 book 节点
  3. 从第一个 book 元素节点中删除 "category" 属性

根据对象删除属性节点

removeAttributeNode(node) 方法通过使用 node 对象作为参数,来删除属性节点。

实例: removeAttributeNode(x)

下面的代码片段删除所有 <book> 元素的所有属性:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.getElementsByTagName("book");
 
for (i=0;i<x.length;i++)
{
  while (x[i].attributes.length>0)
  {
    attnode=x[i].attributes[0];
    old_att=x[i].removeAttributeNode(attnode);
  }
}

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 使用 getElementsByTagName() 来获取所有 book 节点
  3. 检查每个 book 元素是否拥有属性
  4. 如果在某个 book 元素中存在属性,则删除该属性

XML DOM 替换节点


replaceChild() 方法替换指定节点。

nodeValue 属性替换文本节点中的文本。


替换元素节点

replaceChild() 方法用于替换节点。

下面的代码片段替换第一个 <book> 元素:

xmlDoc=loadXMLDoc("books.xml");
 
x=xmlDoc.documentElement;
 
// 创建新的 book 元素, title 元素及 node 节点
newNode=xmlDoc.createElement("book");
newTitle=xmlDoc.createElement("title");
newText=xmlDoc.createTextNode("A Notebook");
 
// 将 text 节点添加到 title 节点中
newTitle.appendChild(newText);
// 将 title 节点添加到  book 节点中
newNode.appendChild(newTitle);
 
y=xmlDoc.getElementsByTagName("book")[0]
// 使用新节点替换第一个 book 节点
x.replaceChild(newNode,y);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的元素节点 <book>
  3. 创建一个新的元素节点 <title>
  4. 创建一个新的文本节点,带有文本 "A Notebook"
  5. 向新元素节点 <title> 追加这个新文本节点
  6. 向新元素节点 <book> 追加这个新元素节点 <title>
  7. 把第一个 <book> 元素节点用新的 <book> 元素节点替换

替换文本节点中的数据

replaceData() 方法用于替换文本节点中的数据。

replaceData() 方法有三个参数:

  • offset - 在何处开始替换字符。offset 值以 0 开始。
  • length - 要替换多少字符
  • string - 要插入的字符串
xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];

x.replaceData(0,8,"Easy");

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取第一个 <title> 元素节点的文本节点
  3. 使用 replaceData 方法把文本节点的前 8 个字符替换为 "Easy"

使用 nodeValue 属性代替

用 nodeValue 属性来替换文本节点中数据会更加容易。

下面的代码片段将用 "Easy Italian" 替换第一个 <title> 元素中的文本节点值:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];

x.nodeValue="Easy Italian";

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取第一个 <title> 元素节点的文本节点
  3. 使用 nodeValue 属性来更改这个文本节点的文本

DOM 创建节点 

创建新的元素节点

createElement() 方法创建一个新的元素节点:

xmlDoc=loadXMLDoc("books.xml");

newel=xmlDoc.createElement("edition");

x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的元素节点 <edition>
  3. 向第一个 <book> 元素追加这个元素节点

创建新的属性节点

createAttribute() 用于创建一个新的属性节点:

xmlDoc=loadXMLDoc("books.xml");

newatt=xmlDoc.createAttribute("edition");
newatt.nodeValue="first";

x=xmlDoc.getElementsByTagName("title");
x[0].setAttributeNode(newatt);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的属性节点 "edition"
  3. 设置属性节点的值为 "first"
  4. 向第一个 <title> 元素添加这个新的属性节点

使用 setAttribute() 创建属性

由于 setAttribute() 方法可以在属性不存在的情况下创建新的属性,我们可以使用这个方法来创建一个新的属性。

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName('book');
x[0].setAttribute("edition","first");

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 为第一个 <book> 元素设置(创建)值为 "first" 的 "edition" 属性

创建文本节点

createTextNode() 方法创建一个新的文本节点:

xmlDoc=loadXMLDoc("books.xml");

newel=xmlDoc.createElement("edition");
newtext=xmlDoc.createTextNode("first");
newel.appendChild(newtext);

x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新元素节点 <edition>
  3. 创建一个新的文本节点,其文本是 "first"
  4. 向这个元素节点追加新的文本节点
  5. 向第一个 <book> 元素追加新的元素节点

创建 CDATA Section 节点

createCDATASection() 方法创建一个新的 CDATA section 节点。

xmlDoc=loadXMLDoc("books.xml");

newCDATA=xmlDoc.createCDATASection("Special Offer & Book Sale");

x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newCDATA);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的 CDATA section 节点
  3. 向第一个 <book> 元素追加这个新的 CDATA section 节点

创建注释节点

createComment() 方法创建一个新的注释节点。

xmlDoc=loadXMLDoc("books.xml");

newComment=xmlDoc.createComment("Revised March 2008");

x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newComment);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的注释节点
  3. 把这个新的注释节点追加到第一个 <book> 元素

DOM 添加节点 


添加节点 - appendChild()

appendChild() 方法向一个已有的节点添加一个子节点。

新节点会添加(追加)到任何已有的子节点之后。

注意:如果节点的位置很重要,请使用 insertBefore() 方法。

下面的代码片段创建一个元素(<edition>),并把它添加到第一个 <book> 元素的最后一个子节点后面:

xmlDoc=loadXMLDoc("books.xml");

newel=xmlDoc.createElement("edition");

x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新节点 <edition>
  3. 把这个节点追加到第一个 <book> 元素

插入节点 - insertBefore()

insertBefore()方法用于在指定的子节点之前插入节点。

在被添加的节点的位置很重要时,此方法很有用:

xmlDoc=loadXMLDoc("books.xml");

newNode=xmlDoc.createElement("book");

x=xmlDoc.documentElement;
y=xmlDoc.getElementsByTagName("book")[3];

x.insertBefore(newNode,y);

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 创建一个新的元素节点 <book>
  3. 把这个新节点插到最后一个 <book> 元素节点之前

如果 insertBefore() 的第二个参数是 null,新节点将被添加到最后一个已有的子节点之后。

x.insertBefore(newNode,null) 和 x.appendChild(newNode) 都可以向 x 追加一个新的子节点。

添加新属性

addAtribute() 这个方法是不存在的。

如果属性不存在,则 setAttribute() 可创建一个新的属性:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName('book');
x[0].setAttribute("edition","first");

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 把第一个 <book> 元素的 "edition" 属性的值设置(创建)为 "first"

注意:如果属性已存在,setAttribute() 方法将覆盖已有的值。

向文本节点添加文本 - insertData()

insertData() 方法将数据插入已有的文本节点中。

insertData() 方法有两个参数:

  • offset - 在何处开始插入字符(以 0 开始)
  • string - 要插入的字符串

下面的代码片段将把 "Easy" 添加到已加载的 XML 的第一个 <title> 元素的文本节点:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];

x.insertData(0,"Easy ");

DOM 克隆节点

cloneNode() 方法创建指定节点的副本。

cloneNode() 方法有一个参数(true 或 false)。该参数指示被克隆的节点是否包括原节点的所有属性和子节点。

下面的代码片段复制第一个 <book> 节点,并把它追加到文档的根节点:

xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName('book')[0];
cloneNode=x.cloneNode(true);
xmlDoc.documentElement.appendChild(cloneNode);
 
// 输出所有 title 节点文本值
y=xmlDoc.getElementsByTagName("title");
for (i=0;i<y.length;i++)
{
  document.write(y[i].childNodes[0].nodeValue);
  document.write("<br>");
}

实例解释:

  1. 使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  2. 获取要复制的节点
  3. 使用 cloneNode 方法把节点复制到 "newNode" 中
  4. 向 XML 文档的根节点追加新的节点
  5. 输出文档中所有 book 的所有 titl

XMLHttpRequest 对象


通过 XMLHttpRequest 对象,您可以在不重新加载整个页面的情况下更新网页中的某个部分。

XMLHttpRequest 对象

XMLHttpRequest 对象用于幕后与服务器交换数据。

XMLHttpRequest 对象是开发者的梦想,因为您可以:

  • 在不重新加载页面的情况下更新网页
  • 在页面已加载后从服务器请求数据
  • 在页面已加载后从服务器接收数据
  • 在后台向服务器发送数据

创建 XMLHttpRequest 对象

所有现代的浏览器(IE7+、Firefox、Chrome、Safari 和 Opera)都有一个内建的 XMLHttpRequest 对象。

创建 XMLHttpRequest 对象的语法

xmlhttp=new XMLHttpRequest();

 旧版本的 Internet Explorer(IE5 和 IE6)使用 ActiveX 对象:

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

为了处理所有现代的浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建一个 XMLHttpRequest 对象,如果不支持,则创建一个 ActiveX 对象:

if (window.XMLHttpRequest)
{
  // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
  xmlhttp=new XMLHttpRequest();
}
else
{
  // IE6, IE5 浏览器执行代码
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

发送一个请求到服务器 

为了发送一个请求到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:

xmlhttp.open("GET","xmlhttp_info.txt",true);
xmlhttp.send();
方法描述
open(method,url,async)规定请求的类型,URL,请求是否应该进行异步处理。

method:请求的类型:GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
send(string)发送请求到服务器。

string:仅用于 POST 请求

GET 或 POST

GET 比 POST 简单并且快速,可用于大多数情况下。

然而,下面的情况下请始终使用 POST 请求:

  • 缓存的文件不是一个选项(更新服务器上的文件或数据库)
  • 发送到服务器的数据量较大(POST 没有大小的限制)
  • 发送用户输入(可以包含未知字符),POST 比 GET 更强大更安全

URL - 服务器上的文件

open() 方法的 url 参数,是一个在服务器上的文件的地址:

xmlhttp.open("GET","xmlhttp_info.txt",true);

该文件可以是任何类型的文件(如 .txt 和 .xml),或服务器脚本文件(如.html 和 .php,可在发送回响应之前在服务器上执行动作)。

异步 - True 或 False?

如需异步发送请求,open() 方法的 async 参数必需设置为 true:

xmlhttp.open("GET","xmlhttp_info.txt",true);

发送异步请求对于 Web 开发人员是一个巨大的进步。在服务器上执行的许多任务非常费时。

通过异步发送,JavaScript 不需要等待服务器的响应,但可以替换为:

  • 等待服务器的响应时,执行其他脚本
  • 响应准备时处理响应

Async=true

当使用 async=true 时,在 onreadystatechange 事件中响应准备时规定一个要执行的函数:

xmlhttp.onreadystatechange=function()
{
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
  {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
  }
}
xmlhttp.open("GET","xmlhttp_info.txt",true);
xmlhttp.send();

Async=false

如需使用 async=false,请更改 open() 方法的第三个参数为 false:

xmlhttp.open("GET","xmlhttp_info.txt",false);

不推荐使用 async=false,但如果处理几个小的请求还是可以的。

请记住,JavaScript 在服务器响应准备之前不会继续执行。如果服务器正忙或缓慢,应用程序将挂起或停止。

注意:当您使用 async=false 时,不要编写 onreadystatechange 函数 - 只需要把代码放置在 send() 语句之后即可:

xmlhttp.open("GET","xmlhttp_info.txt",false);
xmlhttp.send();
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

服务器响应

如需从服务器获取响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。

属性描述
responseText获取响应数据作为字符串
responseXMLResponseXML 属性返回 XML 文档对象,可使用 DOM 节点树的方法和属性来检查和解析该对象

responseText 属性

如果来自服务器的响应不是 XML,请使用 responseText 属性。

responseText 属性以字符串形式返回响应,您可以相应地使用它:

document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

responseXML 属性

如果来自服务器的响应是 XML,且您想要把它解析为 XML 对象,请使用 responseXML 属性:

请求文件 cd_catalog.xml 并解析响应:

xmlDoc=xmlhttp.responseXML;
var txt="";
x=xmlDoc.getElementsByTagName("ARTIST");
for (i=0;i<x.length;i++)
{
  txt=txt + x[i].childNodes[0].nodeValue + "";
}
document.getElementById("myDiv").innerHTML=txt;

onreadystatechange 事件

当请求被发送到服务器,我们要根据响应执行某些动作。

onreadystatechange 事件在每次 readyState 变化时被触发。

readyState 属性持有 XMLHttpRequest 的状态。

XMLHttpRequest 对象的三个重要的属性:

属性描述
onreadystatechange存储函数(或函数的名称)在每次 readyState 属性变化时被自动调用
readyState存放了 XMLHttpRequest 的状态。从 0 到 4 变化:
0:请求未初始化
1:服务器建立连接
2:收到的请求
3:处理请求
4:请求完成和响应准备就绪
status200:"OK"
404:找不到页面

在 onreadystatechange 事件中,我们规定当服务器的响应准备处理时会发生什么。

当 readyState 是 4 或状态是 200 时,响应准备:

xmlhttp.onreadystatechange=function()
{
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
  {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
  }
}

 注意:onreadystatechange 事件在每次 readyState 发生变化时被触发,总共触发了四次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值