php如何运用,浅谈如何利用PHP访问和操作DOM

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<?xmlversion ="1.0"encoding="UTF-8"standalone="yes"?>

XML Processing I

John Smith Jr.

HisOwnTM

111-222-333-4441

What is XML about ?

XML (Extensible Markup Language) is a ...

SAX

SAX is a simple API for ...

StAX

Much powerful and flexible, StAX, is very...

DOM

DOM concept

Starting to use DOM...

First DOM application...

Here it is your first DOM application...

The end...

第一个示例应用程序使用Book.xml文档,提取出关联的树,然后使用DOMElement接口的getElementsByTagName方法显示第一个子节点实例:

DOMNodeList DOMElement::getElementsByTagName(string $name):这个方法返回所有$name参数指定的标签名的子元素。下面的例子查找根节点 ,然后查找它的子节点 ,和 元素,选择每个子节点的第一个,最后打印这些节点的值:<?php

// 创建一个文档实例

$doc=newDOMDocument();

//载入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子树,并列出节点的名字和值。functiongetNodesInfo($node)

{

if($node->hasChildNodes())

{

$subNodes=$node->childNodes;

foreach($subNodesas$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=newDOMDocument();

//载入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);

?>

6a8e792168734e9beb6ca23038dfa871.png

图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节点丢失,新的 节点就添加到节点的子节点列表前。

下面的例子创建了一个节点,并将其追加到节点的末尾://创建一个新元素

$newElement= $dom->createElement('bibliography','Martin Didier, Professional XML');

//使用appendChild函数将其追加到根节点

//调用appendChild函数

appendNewChild($root,$newElement);

//这个函数追加了一个新的子节点

function appendNewChild($currentNode, $node)

{

$currentNode->appendChild($node);

}

a16c9206020b38edda5829dd7990518c.png

如果你通过getNodeInfo()函数运行得出结果,你将会看到如图2所示的输出。

图- 2 追加的节点:这个图显示了新加的节点和它的内容

下面的例子是在节点增加一个子节点://创建一个新的元素

$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);

}

54a5cb235d7230f8efca2cd7d6839b00.png

通过getNodesInfo运行修改后的文档,显示新的节点,如图3所示。

图- 3 插入节点:这张图片显示了在节点前插入了子节点

节点克隆

克隆一个节点意味着创建一个和当前节点一模一样的节点,克隆节点时使用cloneNode方法。

DOMNode DOMNode::cloneNode([ bool $deep]):创建当前的克隆,$deep参数指定是否要拷贝当前节点的子节点,其默认值是false。下面的示例代码显示克隆 元素,并作为源元素的子节点,图4显示了输出内容://设置引用节点

$author= $root->getElementsByTagName('author')->item(0);

//调用cloningNode函数

cloningNode($author);

//这个函数克隆$currentNode

function cloningNode($currentNode)

{

$clonenode= $currentNode ->cloneNode(true);

$newnode= $currentNode->appendChild($clonenode);

}

ca59ae15eaad91fa7ebd27f8f4d01aff.png

图- 4 克隆节点:克隆子节点并将其放在源节点下,源节点的文本值变成两份了,因为检索节点的文本值时也检索了其子节点的 值

移除子节点

使用removeChild方法从DOM树中移除子节点。

DOMNode DOMNode::removeChild(DOMNode $oldnode):这个函数移除一个子节点,$oldnode参数指出要移除的子节点。下面的示例代码从Book.xml文档中移除子 节点,从图5中显示的输出内容可以看到bibliography节点消失了。

36756697916caeb4d7152455dd0b02fd.png

图- 5 移除节点:移除最后一个子节点后,重新列出了节点的名称值,显示节点确实被移除了

替换节点

为了用一个新节点替换已有的节点,使用replaceChild方法。

DOMNode DOMNode::replaceChild(DOMNode $newnode, DOMNode $oldnode):这个函数使用$newnode子节点替换$oldnode节点。

例如,假设你想用新的code子节点替换ISBN子节点://获取ISBN节点

$element= $dom->getElementsByTagName('ISBN')->item(0);

//创建新的元素

$code= $dom->createElement('code', '909090');

//调用replacingNode函数

replacingNode($code,$element);

//这个函数使用$node替换$currentNode

function replacingNode($currentNode, $node)

{

$node->parentNode->replaceChild($currentNode, $node);

}

2237a4b6f4525a2f1e207c780db5db43.png

图6中显示的输出内容表明节点被替换了

图- 6 替换节点:这里显示的是用新的节点替换节点后的文档内容

导入节点

使用importNode方法从另一个树拷贝一个节点到当前的树。

DOMNode DOMDocument::importNode(DOMNode $importedNode [,bool $deep]):这个方法从另一个XML文档导入一个节点,然后插入当前文档的DOM树中, $importedNode参数指出了要导入的节点,导入的节点表示原始节点的一份拷贝,因此导入操作不会修改外部树,$deep参数控制是否导入被导入节点的深度,值为 TRUE时,导入完整的节点子树,为FALSE时,只导入节点本身。

下面的示例从Book_continue.xml文件导入节点到Book.xml,下面是Book_continue.xml文档的内容:<?xmlversion ="1.0"encoding="UTF-8"standalone="yes"?>

XPath

XPath is language for...

This chaper is a bonus to...

]]>

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"/>

下面是导入节点的代码:

$olddoc=newDOMDocument;

$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);

?>

f18df0ee7b0b8a3602f8374c0bf807ee.png

图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=newDOMDocument();

//使用缩进格式化输出

$document->formatOutput=true;

//创建一个注释

$comment= $document->createComment('Beautiful flowers!!!');

$document->appendChild( $comment );

//创建根元素

$root= $document->createElement( 'flowers' );

$document->appendChild( $root );

//创建子节点

$tulips= $document->createElement( 'tulips' );

//创建元素的第一个子节点,并设置其属性

$bulbs_1= $document->createElement( 'bulbs' );

$bulbs_1->setAttribute('price','� 7.65');

$bulbs_1->appendChild($document->createTextNode( 'Parrot'));

$tulips->appendChild( $bulbs_1 );

//创建元素的第二个子节点,并设置其属性

$bulbs_2= $document->createElement( 'bulbs' );

$bulbs_2->setAttribute('color','magenta');

$bulbs_2->appendChild($document->createTextNode( 'Lily flowering' ));

$tulips->appendChild( $bulbs_2 );

//追加节点到根节点后

$root->appendChild( $tulips );

//创建CDATA小节

$cdata= $document->createCDATASection(

'Sword Lily'.

'Starface');

$document->appendChild( $cdata );

//保存对象树到Flowers.xml

echo $document->saveXML();

$document->save('Flowers.xml');

?>

新的Flower.xml文档内容如下:

Parrot

Lily flowering

[

Sword Lily

Starface

]]>

清单2中的代码创建了一个对象树,并将其保存为Flowers.xml。

清单2 创建一个新的DOM树

本文简单介绍了PHP 5 DOM扩展,并介绍如何使用它操作XML(或HTML)文档,以及如何从零创建一个DOM树。

【编辑推荐】

点赞 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值