定位 DOM 节点
通过节点间的关系访问节点树中的节点,通常称为定位节点 ("navigating nodes")。
在 XML DOM 中,节点的关系被定义为节点的属性:
- parentNode
- childNodes
- firstChild
- lastChild
- nextSibling
- previousSibling
下面的图像展示了 books.xml 中节点树的一个部分,并说明了节点之间的关系:
DOM - 父节点
所有的节点都仅有一个父节点。下面的代码定位到 <book> 的父节点:
xmlDoc=loadXMLDoc("books.xml");
//获取第一个 <book> 元素
x=xmlDoc.getElementsByTagName("book")[0];
//输出 "x" 的父节点的节点名
document.write(x.parentNode.nodeName);
避免空的文本节点
Firefox,以及其他一些浏览器,把空的空白或换行当作文本节点,而 IE 不会这么做。
这会在使用下列属性使产生一个问题:firstChild、lastChild、nextSibling、previousSibling。
为了避免定位到空的文本节点(元素节点之间的空格和换行符号),我们使用一个函数来检查节点的类型:
function get_nextSibling(n)
{
y=n.nextSibling;
//元素节点的类型是 1。如果同级节点不是元素节点,就移动到下一个节点,直到找到元素节点为止。通过这个办法,在 IE 和 Firefox 中,都可以得到相同的结果。
while (y.nodeType!=1)
{
y=y.nextSibling;
}
return y;
}
有了上面的函数,我们就可以使用 get_nextSibling(node) 来代替 node.nextSibling 属性。
<html>
<head>
<script type="text/javascript" src="loadxmldoc.js">
</script>
<script type="text/javascript">
//check if the first node is an element node
function get_firstChild(n)
{
//获取第一个元素
y=n.firstChild;
//获取最一个元素
//y=n.lastChild;
//获取下一个同级元素
//y=n.nextSibling;
//获取上一个同级元素
//y=n.previousSibling;
while (y.nodeType!=1)
{
y=y.nextSibling;
}
return y;
}
</script>
</head>
<body>
<script type="text/javascript">
xmlDoc=loadXMLDoc("books.xml");
x=get_firstChild(xmlDoc.getElementsByTagName("book")[0]);
document.write(x.nodeName);
</script>
</body>
</html>
获取元素的值
在 DOM 中,每种成分都是节点。元素节点没有文本值。
元素节点的文本存储在子节点中。该节点称为文本节点。
获取元素文本的方法,就是获取这个子节点(文本节点)的值。
获取元素值
getElementsByTagName() 方法返回包含拥有指定标签名的所有元素的节点列表,其中的元素的顺序是它们在源文档中出现的顺序。
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");
//把 txt 变量设置为第一个 title 元素节点的 "lang" 属性的值
txt=xmlDoc.getElementsByTagName("title")[0].getAttribute("lang");
获取属性值 - getAttributeNode()
getAttributeNode() 方法返回属性节点。
下面代码检索第一个 <title> 元素的 "lang" 属性的文本值:
xmlDoc=loadXMLDoc("books.xml");
//获取第一个 <title> 元素节点的 "lang" 属性节点
x=xmlDoc.getElementsByTagName("title")[0].getAttributeNode("lang");
//把 txt 变量设置为属性的值
txt=x.nodeValue;
改变元素的值
在 DOM 中,每种成分都是节点。元素节点没有文本值。
元素节点的文本存储在子节点中。该节点称为文本节点。
改变元素文本的方法,就是改变这个子节点(文本节点)的值。
改变文本节点的值
nodeValue 属性可用于改变文本节点的值。
下面的代码片段改变了第一个 <title> 元素的文本节点值:
xmlDoc=loadXMLDoc("books.xml");
//获取第一个 <title> 元素的文本节点
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
//把此文本节点的节点值更改为 "Hello World"
x.nodeValue="Hello World";
改变属性的值
在 DOM 中,属性也是节点。与元素节点不同,属性节点拥有文本值。
改变属性的值的方法,就是改变它的文本值。
可以通过使用 setAttribute() 方法或属性节点的 nodeValue 属性来完成这个任务
通过使用 setAttribute() 来改变属性
setAttribute() 方法设置已有属性的值,或创建新属性。
下面的代码改变 <book> 元素的 category 属性:
xmlDoc=loadXMLDoc("books.xml");
//获取第一个 <book> 元素
x=xmlDoc.getElementsByTagName('book');
//把 "category" 属性的值更改为 "child"
x[0].setAttribute("category","child");
注释:如果属性节点不存在,则创建一个新属性(拥有指定的名称和值)。
通过使用 nodeValue 改变属性
nodeValue 属性可用于更改属性节点的值:
xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("book")[0]
//获取第一个 <book> 元素的 "category" 属性
y=x.getAttributeNode("category");
//把该属性节点的值更改为 "child"
y.nodeValue="child";
删除元素节点
removeChild() 方法删除指定的节点。
当一个节点被删除时,其所有子节点也会被删除。
下面的代码片段将从载入的 xml 中删除第一个 <book> 元素:
xmlDoc=loadXMLDoc("books.xml");
//把变量 y 设置为要删除的元素节点
y=xmlDoc.getElementsByTagName("book")[0];
//通过使用 removeChild() 方法从父节点删除元素节点
xmlDoc.documentElement.removeChild(y);
删除自身 - 删除当前的节点
removeChild() 方法是唯一可以删除指定节点的方法。
当你已定位需要删除的节点时,就可以通过使用 parentNode 属性和 removeChild() 方法来删除此节点:
xmlDoc=loadXMLDoc("books.xml");
//把变量 y 设置为要删除的元素节点
x=xmlDoc.getElementsByTagName("book")[0];
//通过使用 parentNode 属性和 removeChild() 方法来删除此元素节点
x.parentNode.removeChild(x);
删除文本节点
removeChild() 方法可用于删除文本节点:
xmlDoc=loadXMLDoc("books.xml");
//把变量 x 设置为第一个 title 元素节点
x=xmlDoc.getElementsByTagName("title")[0];
//把变量 y 设置为 要删除的文本节点
y=x.childNodes[0];
//通过使用 removeChild() 方法从父节点删除节点
x.removeChild(y);
注释:不太常用 removeChild() 从节点删除文本。可以使用 nodeValue 属性代替它。请看下一段。
清空文本节点
nodeValue 属性可用于改变或清空文本节点的值:
xmlDoc=loadXMLDoc("books.xml");
//把变量 x 设置为第一个 title 元素的文本节点
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
//使用 nodeValue 属性来清空文本节点的文本
x.nodeValue="";
根据名称删除属性节点
removeAttribute(name) 方法用于根据名称删除属性节点。
Example: removeAttribute('category')
下面的代码片段删除第一个 <book> 元素中的 "category" 属性:
xmlDoc=loadXMLDoc("books.xml");
//使用 getElementsByTagName() 来获取 book 节点
x=xmlDoc.getElementsByTagName("book");
//从第一个 book 元素节点中删除 "category" 属性
x[0].removeAttribute("category");
根据对象删除属性节点
removeAttributeNode(node) 方法通过使用 Node 对象作为参数,来删除属性节点。
Example: removeAttributeNode(x)
下面的代码片段删除所有 <book> 元素的所有属性:
xmlDoc=loadXMLDoc("books.xml");
//使用 getElementsByTagName() 来获取所有 book 节点
x=xmlDoc.getElementsByTagName("book");
//检查每个 book 元素是否拥有属性
for (i=0;i<x.length;i++)
{
//如果在某个 book 元素中存在属性,则删除该属性
while (x[i].attributes.length>0)
{
attnode=x[i].attributes[0];
old_att=x[i].removeAttributeNode(attnode);
}
}
替换元素节点
replaceChild() 方法用于替换节点。
下面的代码片段替换第一个 <book> 元素:
mlDoc=loadXMLDoc("books.xml");
x=xmlDoc.documentElement;
//创建一个 book 元素、一个 title 元素,以及一个 text 节点
newNode=xmlDoc.createElement("book");
newTitle=xmlDoc.createElement("title");
newText=xmlDoc.createTextNode("Hello World");
//向 title 节点添加文本节点
newTitle.appendChild(newText);
//向 book 节点添加 title 节点
newNode.appendChild(newTitle);
y=xmlDoc.getElementsByTagName("book")[0];
//用这个新节点替换第一个 book 节点
x.replaceChild(newNode,y);
替换文本节点中的数据
replaceData() 方法用于替换文本节点中的数据。
replaceData() 方法有三个参数:
- offset - 在何处开始替换字符。Offset 值以 0 开始。
- length - 要替换多少字符
- string - 要插入的字符串
xmlDoc=loadXMLDoc("books.xml");
//获取第一个 <title> 元素节点的文本节点
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
//使用 replaceData 方法把文本节点的前 8 个字符替换为 "hello"
x.replaceData(0,8,"hello");
使用 nodeValue 属性
用 nodeValue 属性来替换文本节点中数据会更加容易。
下面的代码片段将用 "Easy Italian" 替换第一个 <title> 元素中的文本节点值:
xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Hello World";
创建新的元素节点
createElement() 方法创建新的元素节点:
xmlDoc=loadXMLDoc("books.xml");
//创建一个新的元素节点 <edition>
newel=xmlDoc.createElement("edition");
x=xmlDoc.getElementsByTagName("book")[0];
//向第一个 <book> 元素追加这个元素节点
x.appendChild(newel);
创建新的属性节点
createAttribute() 用于创建新的属性节点:
xmlDoc=loadXMLDoc("books.xml");
//创建一个新的属性节点 "edition"
newatt=xmlDoc.createAttribute("edition");
newatt.nodeValue="first";
//向第一个 <title> 元素添加这个新的属性节点
x=xmlDoc.getElementsByTagName("title");
x[0].setAttributeNode(newatt);
注释:如果该属性已存在,则被新属性替代。
通过使用 setAttribute() 来创建属性
由于 setAttribute() 可以在属性不存在的情况下创建新的属性,我们可以使用这个方法来创建新属性。
xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName('book');
//为第一个 <book> 元素设置(创建)值为 "first" 的属性
x[0].setAttribute("edition","first");
创建文本节点
createTextNode() 方法创建新的文本节点:
xmlDoc=loadXMLDoc("books.xml");
//创建一个新元素节点 <edition>
newel=xmlDoc.createElement("edition");
//创建一个新的文本节点,其文本是 "first"
newtext=xmlDoc.createTextNode("first");
//向这个元素节点追加新的文本节点
newel.appendChild(newtext);
//向第一个 <book> 元素追加新的元素节点
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);
创建一个 CDATA Section 节点
createCDATASection() 方法创建一个新的 CDATA section 节点。
xmlDoc=loadXMLDoc("books.xml");
//创建一个新的 CDATA section 节点
newCDATA=xmlDoc.createCDATASection("Special Offer & Book Sale");
//向第一个 <book> 元素追加这个新的 CDATA section 节点
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newCDATA);
创建注释节点
createComment() 方法创建一个新的注释节点。
xmlDoc=loadXMLDoc("books.xml");
//创建一个新的注释节点
newComment=xmlDoc.createComment("Revised March 2008");
//把这个新的注释节点追加到第一个 <book> 元素
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newComment);
添加节点 - appendChild()
appendChild() 方法向已存在的节点添加子节点。
新节点会添加(追加)到任何已存在的子节点之后。
注释:如果节点的位置很重要,请使用 insertBefore() 方法。
下面的代码片段创建一个元素(<edition>),并把它添加到第一个 <book> 元素最后一个子节点后面:
xmlDoc=loadXMLDoc("books.xml");
//创建一个新节点 <edition>
newel=xmlDoc.createElement("edition");
//把这个节点追加到第一个 <book> 元素
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);
插入节点 - insertBefore()
insertBefore() 方法用于在指定的子节点之前插入节点。
在被添加的节点的位置很重要时,此方法很有用。
xmlDoc=loadXMLDoc("books.xml");
//创建一个新的元素节点 <book>
newNode=xmlDoc.createElement("book");
//把这个节点插到最后一个 <book> 元素节点之前
x=xmlDoc.documentElement;
y=xmlDoc.getElementsByTagName("book")[3];
x.insertBefore(newNode,y);
注释:如果 insertBefore() 的第二个参数是 null,新节点将添加到最后一个已有的子节点之后。
x.insertBefore(newNode,null) 和 x.appendChild(newNode) 都可以向 x 追加一个新的子节点
添加新属性
addAtribute() 这个方法是不存在的。
如果属性不存在,则 setAttribute() 可创建一个新的属性:
xmlDoc=loadXMLDoc("books.xml");
//把第一个 <book> 元素的 "edition" 属性的值设置(创建)"first"
x=xmlDoc.getElementsByTagName('book');
x[0].setAttribute("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,"Hello ");
复制节点
cloneNode() 方法创建指定节点的副本。
cloneNode() 方法有一个参数(true 或 false)。该参数指示被复制的节点是否包括原节点的所有属性和子节点。
下面的代码片段拷贝第一个 <book> 节点,并把它追加到文档的根节点:
xmlDoc=loadXMLDoc("books.xml");
//获取要复制的节点
oldNode=xmlDoc.getElementsByTagName('book')[0];
//通过使用 cloneNode 方法把节点复制到 "newNode" 中
newNode=oldNode.cloneNode(true);
//向 XML 文档的根节点追加新节点
xmlDoc.documentElement.appendChild(newNode);
//输出文档中所有 book 的 title
y=xmlDoc.getElementsByTagName("title");
for (i=0;i<y.length;i++)
{
document.write(y[i].childNodes[0].nodeValue);
document.write("<br />");
}
//输出:
Harry Potter
Everyday Italian
XQuery Kick Start
Learning XML
Harry Potter