使用DOM读取XML值
来源:互联网 发布:中日友好靠韩国 知乎 编辑:程序博客网 时间:2024/04/26 16:13
原文:http://developer.51cto.com/art/200907/135051.htm
DOM树定义了文档的逻辑结构,以及控制你访问和操作这些文档的方法。使用DOM,开发人员可以创建XML或HTML文档,操作它们的结果,增加、修改和删除文档 元素及内容。可以从任何编程语言访问DOM,本文使用PHP 5 DOM扩展,它是PHP核心的一部分,因此除了PHP外,不需要安装其它软件。
DOM树节点遵循XML命名规范,如:
1、Document节点 -- 表示DOMDocument接口
2、Element节点 -- 表示DOMElement接口
3、Attribute节点 -- 表示DOMAttr接口
4、Comment节点 -- 表示DOMComment接口
5、Text节点 -- 表示DOMText接口
提取元素
这一小节介绍如何从DOM树中提取元素和值,本文使用Book.xml作为例子进行说明,其内容如清单1所示。
清单1 Book.xml
- <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <book>
- <!--XML Processing [part I] -->
- <name>XML Processing I</name>
- <author>John Smith Jr.</author>
- <publisher>HisOwnTM</publisher>
- <ISBN>111-222-333-4441</ISBN>
- <contents>
- <chapter_I>
- <title>What is XML about ?</title>
- <content>XML (Extensible Markup Language) is a ...</content>
- </chapter_I>
- <chapter_II>
- <title>SAX</title>
- <content>SAX is a simple API for ...</content>
- </chapter_II>
- <chapter_III>
- <title>StAX</title>
- <content>Much powerful and flexible, StAX, is very...</content>
- </chapter_III>
- <chapter_IV>
- <title>DOM
- <subtitle>DOM concept
- <continut>Starting to use DOM...</continut>
- </subtitle>
- <subchapter_IV_I>
- <title>First DOM application...</title>
- <content>Here it is your first DOM application...</content>
- </subchapter_IV_I>
- </title>
- </chapter_IV>
- <end>The end...</end>
- </contents>
- <!-- See you in XML Processing [part II] -->
- </book>
先下载本文使用的PHP代码压缩包,http://assets.devx.com/sourcecode/41975_oa_mainsource.zip,将Book.xml和压 缩包解压后放在同一个目录下。
第一个示例应用程序使用Book.xml文档,提取出关联的树,然后使用DOMElement接口的getElementsByTagName方法显示第一个子节点实例:
DOMNodeList DOMElement::getElementsByTagName(string $name):这个方法返回所有$name参数指定的标签名的子元素。下面的例子查找<book>根节点 ,然后查找它的子节点 <author>,<publisher>和 <name>元素,选择每个子节点的第一个,最后打印这些节点的值:
- <?php
- // 创建一个文档实例
- $doc = new DOMDocument();
- //载入Book.xml文件
- $doc->load( 'Book.xml' );
- //使用book标签名搜索所有元素
- $books = $doc->getElementsByTagName( "book" );
- //使用author标签名搜索所有元素
- $authors = $doc->getElementsByTagName( "author" );
- //返回第一个标签名为author的元素
- $author = $authors->item(0)->nodeValue;
- //以publisher标签名搜索所有元素
- $publishers = $doc->getElementsByTagName( "publisher" );
- //返回第一个找到的标签名为publisher的元素
- $publisher = $publishers->item(0)->nodeValue;
- //搜索标签名为name的所有元素
- $titles = $doc->getElementsByTagName( "name" );
- //返回标签名为name的第一个找到的元素
- $title = $titles->item(0)->nodeValue;
- //打印找到的值
- echo "$title - $author - $publisher \n";
- ?>
最后一行是打印第一个标题,第一个作者,第一个出版商,使用连字符分隔,输出:
XML Processing I - John Smith Jr. - HisOwnTM
递归浏览DOM树
因为XML文档结构中一个标签可以包括另一个标签(分支树),剩下就是叶子节点,因此你可以浏览完整的树或从任何节点开始递归浏览子树 。下面的例子是从任何开始节点($node)浏览下面的XML子树,并列出节点的名字和值。
- function getNodesInfo($node)
- {
- if ($node->hasChildNodes())
- {
- $subNodes = $node->childNodes;
- foreach ($subNodes as $subNode)
- {
- if (($subNode->nodeType != 3) ||
- (($subNode->nodeType == 3) &&
- (strlen(trim($subNode->wholeText))>=1)))
- {
- echo "Node name: ".$subNode->nodeName."\n";
- echo "Node value: ".$subNode->nodeValue."\n";
- }
- getNodesInfo($subNode);
- }
- }
- }
上面的例子使用下面的条件去除了所有空文本节点,让输出看起来更干净:
- if (($subNode->nodeType != 3) ||
- (($subNode->nodeType == 3) &&
- (strlen(trim($subNode->wholeText))>=1)))
前面的代码检查节点是否被处理,同样,你可以设置预定义的preserveWhiteSpace属性,它移除冗余的空白,默认值是TRUE。
为了测试这个功能,下面这个例子传递Book.xml文档的根节点给递归函数getNodesInfo,然后打印出整个DOM树的标签和值:
- <?php
- //创建一个文档实例
- $doc = new DOMDocument();
- //载入Book.xml文件
- $doc->load( 'Book.xml' );
- //设置对象树根
- $root = $dom->firstChild;
- // 递归函数列出子树的所有节点
- function getNodesInfo($node)
- {
- if ($node->hasChildNodes())
- {
- $subNodes = $node->childNodes;
- foreach ($subNodes as $subNode)
- {
- if (($subNode->nodeType != 3) ||
- (($subNode->nodeType == 3)
- &&(strlen(trim($subNode->wholeText))>=1)))
- {
- echo "Node name: ".$subNode->nodeName."\n";
- echo "Node value: ".$subNode->nodeValue."\n";
- }
- getNodesInfo($subNode);
- }
- }
- }
- //调用getNodesInfo函数
- getNodesInfo($root);
- ?>
图1显示了输出的小部分内容
图- 1文档内容:这个图显示了通过getNodesInfo递归函数运行Book.xml的部分输出内容
增加新节点
DOMNode接口包括多个创建新节点和在DOM树中插入节点的方法,如果要创建一个新节点,可以使用createElement或createTextNode方法,然后 ,为了增加一个新节点到DOM树上,可以调用appendChild或insertBefore方法,appendChild方法增加一个新的子节点到特定节点的子节点列表的后面,而 insertBefore方法是在特定节点的前面插入一个节点。
下面是这些方法的原型:
1、DOMElement createElement(string $name [, string $value ]) :这个方法创建了一个DOMElement类的实例,$name参数表示新元素的标签名,$value参数 表示元素的值,你也可以稍后使用DOMElement->nodeValue属性其值。
2、DOMText createTextNode(string $content):这个方法创建了一个DOMText类的实例,$content参数表示新的文本节点的文本内容。
3、DOMNode DOMNode::appendChild(DOMNode $newnode):这个函数扩展了现有子节点末尾$newnode参数,或创建一个新的包括指定节点的子节点列表。
4、DOMNode DOMNode::insertBefore(DOMNode $newnode [,DOMNode $refnode]):这个方法在$refnode节点前插入$newnode参数,如果$refnode节点丢失,新的 节点就添加到节点的子节点列表前。
下面的例子创建了一个<bibliography>节点,并将其追加到节点的末尾:
- //创建一个新元素
- $newElement = $dom->createElement('bibliography','Martin Didier, Professional XML');
- //使用appendChild函数将其追加到根节点
- //调用appendChild函数
- appendNewChild($root,$newElement);
- //这个函数追加了一个新的子节点
- function appendNewChild($currentNode, $node)
- {
- $currentNode->appendChild($node);
- }
如果你通过getNodeInfo()函数运行得出结果,你将会看到如图2所示的输出。
图- 2 追加的节点:这个图显示了新加的<bibliography>节点和它的内容
下面的例子是在<publisher>节点增加一个<foreword>子节点:
- //创建一个新的<foreword>元素
- $newElement = $dom->createElement('foreword',
- 'What I love about this book is that it '.
- 'grew out of just such a process, '.
- 'and shows it on every page.');
- //设置引用节点
- $allContents = $dom->getElementsByTagName('publisher');
- $contents = $allContents->item(0);
- //调用insertNewChild函数
- insertNewChild($contents,$newElement);
- //这个函数插入一个新的子节点作为 $currentNode的第一个子节点
- function insertNewChild($currentNode, $node)
- {
- $currentNode->insertBefore(
- $node, $currentNode->firstChild);
- }
通过getNodesInfo运行修改后的文档,显示新的节点,如图3所示。
图- 3 插入节点:这张图片显示了在<publisher>节点前插入了<foreward>子节点
节点克隆
克隆一个节点意味着创建一个和当前节点一模一样的节点,克隆节点时使用cloneNode方法。
DOMNode DOMNode::cloneNode([ bool $deep]):创建当前的克隆,$deep参数指定是否要拷贝当前节点的子节点,其默认值是false。下面的示例代码显示克隆 <author>元素,并作为源<author>元素的子节点,图4显示了输出内容:
- //设置引用节点
- $author = $root->getElementsByTagName('author')->item(0);
- //调用cloningNode函数
- cloningNode($author);
- //这个函数克隆$currentNode
- function cloningNode($currentNode)
- {
- $clonenode = $currentNode -> cloneNode(true);
- $newnode = $currentNode->appendChild($clonenode);
- }
图- 4 克隆节点:克隆<author>子节点并将其放在源<author>节点下,源节点的文本值变成两份了,因为检索节点的文本值时也检索了其子节点的 值
移除子节点
使用removeChild方法从DOM树中移除子节点。
DOMNode DOMNode::removeChild(DOMNode $oldnode):这个函数移除一个子节点,$oldnode参数指出要移除的子节点。下面的示例代码从Book.xml文档中移除子 节点,从图5中显示的输出内容可以看到bibliography节点消失了。
图- 5 移除节点:移除最后一个子节点<bibliography>后,重新列出了节点的名称值,显示节点确实被移除了
替换节点
为了用一个新节点替换已有的节点,使用replaceChild方法。
DOMNode DOMNode::replaceChild(DOMNode $newnode, DOMNode $oldnode):这个函数使用$newnode子节点替换$oldnode节点。
例如,假设你想用新的code子节点替换ISBN子节点:
- //获取ISBN节点
- $element = $dom->getElementsByTagName('ISBN')->item(0);
- //创建新的<code>元素
- $code = $dom->createElement('code', '909090');
- //调用replacingNode函数
- replacingNode($code,$element);
- //这个函数使用$node替换$currentNode
- function replacingNode($currentNode, $node)
- {
- $node->parentNode->replaceChild($currentNode, $node);
- }
图6中显示的输出内容表明节点被替换了
图- 6 替换节点:这里显示的是用新的<code>节点替换<ISBN>节点后的文档内容
导入节点
使用importNode方法从另一个树拷贝一个节点到当前的树。
DOMNode DOMDocument::importNode(DOMNode $importedNode [,bool $deep]):这个方法从另一个XML文档导入一个节点,然后插入当前文档的DOM树中, $importedNode参数指出了要导入的节点,导入的节点表示原始节点的一份拷贝,因此导入操作不会修改外部树,$deep参数控制是否导入被导入节点的深度,值为 TRUE时,导入完整的节点子树,为FALSE时,只导入节点本身。
下面的示例从Book_continue.xml文件导入<continue>节点到Book.xml,下面是Book_continue.xml文档的内容:
- <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <!--chapter V-->
- <continue>
- <chapter_V>
- <title>XPath</title>
- <content>XPath is language for...</content>
- </chapter_V>
- <![CDATA[
- This chaper is a bonus to...
- ]]>
- <printing cap_I="click_here_for_chapter_I"
- cap_II="click_here_for_chapter_II"
- cap_III="click_here_for_chapter_III"
- cap_IV="click_here_for_chapter_IV"
- cap_V="click_here_for_chapter_V" />
- </continue>
- 下面是导入<continue>节点的代码:
- <?php
- $olddoc = new DOMDocument;
- $olddoc->load("Book_continue.xml");
- //我想导入到一个新文档的节点
- $node = $olddoc->getElementsByTagName("continue")->item(0);
- $newnewdoc = new DOMDocument;
- $newdoc->formatOutput = true;
- $newdoc->load("Book.xml");
- //导入节点及其所有子节点到文档
- $node = $newdoc->importNode($node, true);
- //然后追加到根节点
- $newdoc->documentElement->appendChild($node);
- echo "\nThe 'new document' after copying the nodes into it:\n";
- $root = $newdoc->firstChild;
- function getNodesInfo($node)
- {
- if ($node->hasChildNodes())
- {
- $subNodes = $node->childNodes;
- foreach ($subNodes as $subNode)
- {
- if (($subNode->nodeType != 3) ||
- (($subNode->nodeType ==3) &&
- (strlen(trim($subNode->wholeText))>=1)))
- {
- echo "Node name: ".$subNode->nodeName."\n";
- echo "Node value: ".$subNode->nodeValue."\n";
- }
- getNodesInfo($subNode);
- }
- }
- }
- getNodesInfo($root);
- ?>
图7显示前面代码的输出
图- 7 导入节点:这里显示了从Book_continue.xml导入节点并追加到Book.xml后的样子
检查节点的等同性
检查两个节点是否相同使用isSameNode方法。
bool DOMNode::isSameNode(DOMNode $node):当节点是相等的时候,这个函数返回一个布尔值TRUE,否则返回FALSE,$node参数表示你要和当前节点进行比较 的节点。
注意比较不是基于节点的内容进行的:
- //检查两个节点是否相同
- $author1 = $root->getElementsByTagName('autor')->item(0);
- $author2 = $root->getElementsByTagName('autor')->item(1);
- //调用verifyNodes函数
- verifyNodes($author1,$author2);
- function verifyNodes($currentNode, $node)
- {
- if (($currentNode->isSameNode($node))==true)
- {
- echo "These two nodes are the same";
- }
- }
创建新的树
PHP 5 DOM扩展可以让你从零开始构建DOM树,下面的示例创建了一个全新的XML文档,使用了两个新函数创建注释和CDATA节点。
1、DOMComment DOMDocument::createComment(string $data):创建一个新的注释节点,$data参数表示节点的内容。
2、DOMCDATASection DOMDocument::createCDATASection(string $data):创建一个新的CDATA节点,$data参数表示节点的内容。
- <?php
- //创建一个文档实例
- $document = new DOMDocument();
- //使用缩进格式化输出
- $document->formatOutput = true;
- //创建一个注释
- $comment = $document->createComment('Beautiful flowers!!!');
- $document->appendChild( $comment );
- //创建<flowers>根元素
- $root = $document->createElement( 'flowers' );
- $document->appendChild( $root );
- //创建<tulips>子节点
- $tulips = $document->createElement( 'tulips' );
- //创建<tulips>元素的第一个子节点<bulbs>,并设置其属性
- $bulbs_1 = $document->createElement( 'bulbs' );
- $bulbs_1->setAttribute('price','€ 7.65');
- $bulbs_1->appendChild($document->createTextNode( 'Parrot'));
- $tulips->appendChild( $bulbs_1 );
- //创建<tulips>元素的第二个子节点<bulbs>,并设置其属性
- $bulbs_2 = $document->createElement( 'bulbs' );
- $bulbs_2->setAttribute('color','magenta');
- $bulbs_2->appendChild($document->createTextNode( 'Lily flowering' ));
- $tulips->appendChild( $bulbs_2 );
- //追加<tulips>节点到根节点后
- $root->appendChild( $tulips );
- //创建CDATA小节
- $cdata = $document->createCDATASection(
- '<gladiolus><species>Sword Lily</species>'.
- '<species>Starface</species></gladiolus>');
- $document->appendChild( $cdata );
- //保存对象树到Flowers.xml
- echo $document->saveXML();
- $document->save('Flowers.xml');
- ?>
- 新的Flower.xml文档内容如下:
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <!--Beautiful flowers!!!-->
- <flowers>
- <tulips>
- <bulbs price="€ 7.65">Parrot</bulbs>
- <bulbs color="magenta">Lily flowering</bulbs>
- </tulips>
- </flowers>
- <![CDATA[<gladiolus>
- <species>Sword Lily</species>
- <species>Starface</species>
- </gladiolus>
- ]]>
清单2中的代码创建了一个对象树,并将其保存为Flowers.xml。
清单2 创建一个新的DOM树
本文简单介绍了PHP 5 DOM扩展,并介绍如何使用它操作XML(或HTML)文档,以及如何从零创建一个DOM树。
- 使用DOM读取XML值
- 使用DOM读取XML文件
- 使用DOM读取XML文件
- 使用DOM读取XML文件
- 使用xml.dom.minidom读取xml文件中的值
- Java 使用DOM创建和读取XML
- Java使用dom读取xml文件
- python学习:使用xml.dom.minidom读取xml文档内容
- Java解析XML(一) 使用DOM读取XML文件
- DOM 读取XML字符串
- DOM方式读取XML
- javascript dom读取xml
- DOM读取xml文件
- DOM读取XML文件
- [Source Code]使用Dom和dom4j读取XML文件
- java读取XML文件,使用3wc.dom.*包
- android测试:使用DOM读取xml文件的内容
- 使用SAX或者DOM或者pull读取XML文件
- Linux下NAT功能的实现 do_bindings()
- java读写文件大全
- Andriod开发配置
- 应用程序-特定 权限设置未将 COM 服务器应用程序(CLSID 为 {BA126AD1-2166-11D1-B1D0-00805FC1270E} )的 本地 激活 权限授予用户 NT AUTHOR
- ScrollView嵌套ListView冲突问题的最优解决方案
- 使用DOM读取XML值
- 京东典型广告推广源码示例一
- SQL Server 2008基础教程 第七章 操纵数据
- 错误: Conversion to Dalvik format failed: Unable to execute dex
- 18.一次性计划任务
- spring+mybatis
- Linux Shell 1>/dev/null 2>&1 含义
- 完全卸载mysql步骤
- Yii框架学习(一)—–Yii的使用、配置及gii使用示例