设为首页收藏本站language→→ 语言切换

鸿鹄论坛

 找回密码
 论坛注册

QQ登录

先注册再绑定QQ

查看: 1400|回复: 1
收起左侧

PHP 中的 SimpleXML 处理

[复制链接]
发表于 2010-2-24 13:39:59 | 显示全部楼层 |阅读模式
<BLOCKQUOTE>了解和 <U><STRONG><FONT color=#000066>HP</FONT></STRONG></U> 版本 5 捆绑到一起的 SimpleXML 扩展,它使 PHP 页面能够以 PHP 友好的语法来查询、搜索、修改和重新发布 <U><STRONG><FONT color=#000066>XML</FONT></STRONG></U>。 </BLOCKQUOTE><!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include <a href="javascript:;" onClick="javascript:tagshow(event, 'java');" target="_self"><u><strong>java</strong></u></a> script once we verify teams wants to use this_and_it will work on dbcs_and_cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES--><>HP 版本 5 引入了 SimpleXML,一种用于读写 XML 的新的应用程序编程接口(API)。在 SimpleXML 中,下面的这样的表达式:</P><TABLE cellSpacing=0 cellPadding=0 width="50%" border=0><TBODY><TR><TD ><RE >$doc-&gt;rss-&gt;channel-&gt;item-&gt;title</PRE></TD></TR></TBODY></TABLE><BR><>从文档中选择元素。只要熟悉文档的结构,很容易编写这种表达式。但是,如果不很清楚需要的元素出现在何处(比如 Docbook、<U><STRONG><FONT color=#000066>HTML</FONT></STRONG></U> 和类似的叙述性文档中),SimpleXML 可以使用 XPath 表达式寻找这些元素。</P><><U><FONT color=#000066>开始使用 SimpleXML</FONT></U></P><>假设需要一个 PHP 页面将 <U><STRONG><FONT color=#000066>RSS</FONT></STRONG></U> 提要(feed)转化成 HTML。<I>RSS</I> 是一种简单的 XML 格式用于发布连锁内容。文档的根元素是 <CODE><FONT face=NSimsun>rss</FONT></CODE>,它包括一个 <CODE><FONT face=NSimsun>channel</FONT></CODE> 元素。<CODE><FONT face=NSimsun>channel</FONT></CODE> 元素包含关于提要的元数据,如标题、语言和 URL。它还包含各种封装在 <CODE><FONT face=NSimsun>item</FONT></CODE> 元素中的报道。每个 <CODE><FONT face=NSimsun>item</FONT></CODE> 都有一个 <CODE><FONT face=NSimsun>link</FONT></CODE> 元素,包括一个 URL,还有 <CODE><FONT face=NSimsun>title</FONT></CODE> 或 <CODE><FONT face=NSimsun>description</FONT></CODE>(通常两者都有),包含普通文本。不使用名称空间。RSS 的内容当然不止这些,不过对本文来说知道这些就足够了。<FONT color=#5c81a7><U>清单 1</U></FONT> 显示了一个典型的例子,它包含两个新闻项。</P><BR><B><U><FONT color=#000066>清单 1. RSS 提要</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;rss version="0.92"&gt;&lt;channel&gt;  &lt;title&gt;Mokka mit Schlag&lt;/title&gt;  &lt;link&gt;http://www.elharo.com/blog&lt;/link&gt;  &lt;language&gt;en&lt;/language&gt;  &lt;item&gt;    &lt;title&gtenn Station: Gone but not Forgotten&lt;/title&gt;    &lt;description&gt;     The old Penn Station in New York was torn down before I was born.      Looking at these pictures, that feels like a mistake.  The current site is      functional, but no more; really just some office towers_and_underground      corridors of no particular interest_or_beauty. The new Madison Square...    &lt;/description&gt;    &lt;link&gt;http://www.elharo.com/blog/new-york/2006/07/31/penn-station&lt;/link&gt;  &lt;/item&gt;  &lt;item&gt;    &lt;title&gtersonal for Elliotte Harold&lt;/title&gt;    &lt;description&gt;Some people use very obnoxious spam filters that require you      to type some random string in your subject such as E37T to get through.      Needless to say neither I nor most other people bother to communicate with      these paranoids. They are grossly overreacting to the spam problem.      Personally I won't ...&lt;/description&gt;    &lt;link&gt;http://www.elharo.com/blog/tech/2006/07/28/personal-for-elliotte-harold/&lt;/link&gt;  &lt;/item&gt;&lt;/channel&gt;&lt;/rss&gt;</PRE></TD></TR></TBODY></TABLE><BR><>我们来开发一个 PHP 页面将 RSS 提要格式化为 HTML。<FONT color=#5c81a7><U>清单 2</U></FONT> 显示了这个页面的基本结构。</P><BR><B><U><FONT color=#000066>清单 2. PHP 代码的静态结构</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?php // Load_and_parse the XML document ?&gt;&lt;html xml:lang="en" lang="en"&gt;&lt;head&gt;  &lt;title&gt;&lt;?php // The title will be read from the RSS ?&gt;&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;&lt;?php // The title will be read from the RSS again ?&gt;&lt;/h1&gt;&lt;?php// Here we'll put a loop to include each item's title_and_description?&gt;&lt;/body&gt;&lt;/html&gt;</PRE></TD></TR></TBODY></TABLE><BR><><STRONG><FONT face=Arial color=#000066 size=3><U>解析 XML 文档</U></FONT></STRONG></P><>第一步是解析 XML 文档并保存到变量中。只需要一行代码,向 <CODE><FONT face=NSimsun>simplexml_load_file()</FONT></CODE> 函数传递一个 URL 即可:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$rss =  simplexml_load_file('http://partners.userland.com/nytRss/nytHomepage.xml');</PRE></TD></TR></TBODY></TABLE><BR><TABLE cellSpacing=0 cellPadding=0 width="40%" align=right border=0><TBODY><TR><TD width=10><IMG title=点击图片可在新窗口打开  pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=10></TD><TD><TABLE cellSpacing=0 cellPadding=5 width="100%" border=1><TBODY><TR><TD bgColor=#eeeeee><B><U><FONT color=#000066>警告</FONT></U></B><BR><>这里选择的方案绝不是最佳方案。实际上不应该每次单击页面时都加载和解析 RSS 提要。对于该页面的读者来说这样做太慢,而且可能造成所加载 RSS 提要的拒绝服务,多数 RSS 都规定了适当的每小时最大的刷新次数。真正的解决方案应该缓冲生成的 HTML 页面、RSS 提要或两者。但是,我们重点是使用 SimpleXML 库,因此这里没有过多考虑。</P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><>对于这个例子,我已经从 Userland 的 <I>New York Times</I> 提要(在 http://partners.userland.com/nytRss/nytHomepage.xml)填充了页面。当然,也可使用其他 RSS 提要的任何 URL。</P><>要注意,虽然名称为 <CODE><FONT face=NSimsun>simplexml_load_<I>file</I>()</FONT></CODE>,该函数实际上解析远程 HTTP URL 上的 XML 文档。但这并不是该函数唯一令人感到奇怪的地方。返回值(这里存储在 <CODE><FONT face=NSimsun>$rss</FONT></CODE> 变量中)并没有指向整个文档,如果使用过其他 API 如文档<U><STRONG><FONT color=#000066>对象</FONT></STRONG></U>模型(DOM)您可能会这样期望。相反,它指向文档的根元素。从 SimpleXML 不能访问文档序言和结语部分的内容。</P><><STRONG><FONT face=Arial color=#000066 size=3><U>寻找提要标题</U></FONT></STRONG></P><>整个提要的标题(不是提要中各报道的标题)位于 <CODE><FONT face=NSimsun>rss</FONT></CODE> 根元素 <CODE><FONT face=NSimsun>channel</FONT></CODE> 的 <CODE><FONT face=NSimsun>title</FONT></CODE> 孩子中。很容易找到这个标题,就仿佛 XML 文档是类 <CODE><FONT face=NSimsun>rss</FONT></CODE> 的一个对象的序列化形式,它的 <B>channel</B> 字段本身带有一个 <B>title</B> 字段。使用常规 PHP 对象引用语法,寻找标题的语句如下:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$title =  $rss-&gt;channel-&gt;title;</PRE></TD></TR></TBODY></TABLE><BR><>找到之后可以将其添加到输出 HTML 中。这样做很简单,只要回显 <CODE><FONT face=NSimsun>$title</FONT></CODE> 变量即可:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >&lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;</PRE></TD></TR></TBODY></TABLE><BR><>这一行输出元素的字符串值而不是整个元素。就是说写入文本内容但不包括标签。</P><>甚至可以完全跳过中间变量 <CODE><FONT face=NSimsun>$title</FONT></CODE>:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >&lt;title&gt;&lt;?php echo $rss-&gt;channel-&gt;title; ?&gt;&lt;/title&gt;</PRE></TD></TR></TBODY></TABLE><BR><>因为该页面在多处重用这个值,我发现用一个含义明确的变量来存储会更方便。</P><><STRONG><FONT face=Arial color=#000066 size=3><U>迭代新闻项</U></FONT></STRONG></P><>然后必须发现提要中的项。完成这项任务的表达式很简单:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$rss-&gt;channel-&gt;item</PRE></TD></TR></TBODY></TABLE><BR><>但是,提要通常包含多个新闻项。但也可能一个也没有。因此,该语句返回一个数组,可以通过 <CODE><FONT face=NSimsun>for-each</FONT></CODE> 循环来遍历它:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >foreach ($rss-&gt;channel-&gt;item as $item) {  echo "&lt;h2&gt;" . $item-&gt;title . "&lt;/h2&gt;";  echo "&lt;p&gt;" . $item-&gt;description . "&lt;/p&gt;";} </PRE></TD></TR></TBODY></TABLE><BR><>通过从 RSS 提要中读取 <CODE><FONT face=NSimsun>link</FONT></CODE> 元素值添加链接也很容易。只要在 PHP 中输出一个 <CODE><FONT face=NSimsun>a</FONT></CODE> 元素,并使用 <CODE><FONT face=NSimsun>$item-&gt;link</FONT></CODE> 检索 URL 即可。<FONT color=#5c81a7><U>清单 3</U></FONT> 增加了该元素并填充到 <FONT color=#5c81a7><U>清单 1</U></FONT> 的框架中。</P><BR><B><U><FONT color=#000066>清单 3. 简单而完整的 PHP RSS 阅读器</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?php // Load_and_parse the XML document $rss =  simplexml_load_file('http://partners.userland.com/nytRss/nytHomepage.xml');$title =  $rss-&gt;channel-&gt;title;?&gt;&lt;html xml:lang="en" lang="en"&gt;&lt;head&gt;  &lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;&lt;?php echo $title; ?&gt;&lt;/h1&gt;&lt;?php// Here we'll put a loop to include each item's title_and_descriptionforeach ($rss-&gt;channel-&gt;item as $item) {  echo "&lt;h2&gt;&lt;a href='" . $item-&gt;link . "'&gt;" . $item-&gt;title . "&lt;/a&gt;&lt;/h2&gt;";  echo "&lt;p&gt;" . $item-&gt;description . "&lt;/p&gt;";}?&gt;&lt;/body&gt;&lt;/html&gt;</PRE></TD></TR></TBODY></TABLE><BR><>这样就用 PHP 完成了一个简单的 RSS 阅读器:只需要几行 HTML 和几行 PHP。不算空白的话一共只有 20 行。当然,这个实现的功能还不够丰富,也不够优化或者健壮。我们来看看还能做什么。</P><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_18r1ofd1244a56-1766-47cc-8c77-f1f4492d2506.gif" width="100%"><BR><IMG title=点击图片可在新窗口打开  pointer" height=6 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=8 border=0></TD></TR></TBODY></TABLE><TABLE  cellSpacing=0 cellPadding=0 align=right><TBODY><TR align=right><TD><IMG title=点击图片可在新窗口打开  pointer" height=4 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"><BR><TABLE cellSpacing=0 cellPadding=0 border=0><TBODY><TR><TD vAlign=center><IMG title=点击图片可在新窗口打开  pointer" height=16 alt="" src="http://www.hh010.com/upload_files/article/242/9_bj2ckb4a785081-dfb2-4172-8d02-ce32ab371ff1.gif" width=16 border=0><BR></TD><TD vAlign=top align=right><B><FONT color=#5c81a7><U>回页首</U></FONT></B></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><><U><FONT color=#000066>错误处理</FONT></U></P><>并非所有 RSS 提要都如期望的那样结构良好。XML 规范要求处理程序在发现结构良好性错误时停止处理文档,SimpleXML 是符合标准的 XML 处理程序。但是在发现错误时它没有提供多少帮助。一般来说,它在 php-errors 文件中记录错误(但是不包括详细的错误消息),<CODE><FONT face=NSimsun>simplexml-load-file()</FONT></CODE> 函数返回 FALSE。如果不能确保解析的文件是结构良好的,在使用文件数据之前要检查错误,如<FONT color=#5c81a7><U>清单 4</U></FONT> 所示。</P><BR><B><U><FONT color=#000066>清单 4. 避免结构错误的输入</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?php$rss =  simplexml_load_file('http://www.cafeaulait.org/today.rss');if ($rss) {  foreach ($rss-&gt;xpath('//title') as $title) {    echo "&lt;h2&gt;" . $title . "&lt;/h2&gt;";  }}else {  echo "Oops! The input is malformed!";}?&gt;</PRE></TD></TR></TBODY></TABLE><BR><>其他常见的错误是文档实际上是结构良好的,但是没有在期望的地方包含期望的元素。如果项没有标题(比如在 top-100 这样的 RSS 提要中),<CODE><FONT face=NSimsun>$doc-&gt;rss-&gt;channel-&gt;item-&gt;title</FONT></CODE> 这样的表达式会怎么样呢?最简单的办法是将返回值永远看作一个数组并循环遍历该数组。这样就可以判断元素比预期的多还是少。但是,如果确定只需要文档中的第一个元素 —— 即使有多个,可以按索引访问,索引号从零开始。比如,如果要请求一个项的标题,可以用如下代码:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$doc-&gt;rss-&gt;channel-&gt;item[0]-&gt;title[0]</PRE></TD></TR></TBODY></TABLE><BR><>如果没有第一项,或者第一项没有标题,该项就按照常规 PHP 数组索引越界处理。即结果是空,在将其插入输出 HTML 时,它会被转化成空白字符串。</P><>识别和拒绝不打算处理的非预期格式通常属于 XML 验证解析器的范畴。然而,SimpleXML 不能针对文档类型定义(DTD)或模式进行验证。它只检查结构良好性。</P><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_18r1ofd1244a56-1766-47cc-8c77-f1f4492d2506.gif" width="100%"><BR><IMG title=点击图片可在新窗口打开  pointer" height=6 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=8 border=0></TD></TR></TBODY></TABLE><TABLE  cellSpacing=0 cellPadding=0 align=right><TBODY><TR align=right><TD><IMG title=点击图片可在新窗口打开  pointer" height=4 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"><BR><TABLE cellSpacing=0 cellPadding=0 border=0><TBODY><TR><TD vAlign=center><IMG title=点击图片可在新窗口打开  pointer" height=16 alt="" src="http://www.hh010.com/upload_files/article/242/9_bj2ckb4a785081-dfb2-4172-8d02-ce32ab371ff1.gif" width=16 border=0><BR></TD><TD vAlign=top align=right><B><FONT color=#5c81a7><U>回页首</U></FONT></B></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><><U><FONT color=#000066>处理名称空间</FONT></U></P><>很多站点现在从 RSS 转向了 Atom。<FONT color=#5c81a7><U>清单 5</U></FONT> 显示了一个 Atom 文档的例子。该文档大部分和 RSS 的例子类似。但是增加了一些元数据,而且根元素变成了 <CODE><FONT face=NSimsun>feed</FONT></CODE> 而不是 <CODE><FONT face=NSimsun>rss</FONT></CODE>。<CODE><FONT face=NSimsun>feed</FONT></CODE> 元素包含 entry 而不是项(item)。<CODE><FONT face=NSimsun>content</FONT></CODE> 元素代替了 <CODE><FONT face=NSimsun>description</FONT></CODE>。最重要的是,Atom 文档使用了名称空间,但 RSS 文档没有。这样,Atom 文档就可以在内容中内嵌真正的、没有转义的可扩展 HTML(XHTML)。</P><BR><B><U><FONT color=#000066>清单 5. Atom 文档</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?xml version="1.0"?&gt;&lt;feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"       xml:base="http://www.cafeconleche.org/today.atom"&gt;  &lt;updated&gt;2006-08-04T16:00:04-04:00&lt;/updated&gt;  &lt;id&gt;http://www.cafeconleche.org/&lt;/id&gt;  &lt;title&gt;Cafe con Leche XML News_and_Resources&lt;/title&gt;  &lt;link rel="self" type="application/atom+xml" href="/today.atom"/&gt;  &lt;rights&gt;Copyright 2006 Elliotte Rusty Harold&lt;/rights&gt;  &lt;entry&gt;    &lt;title&gt;Steve Palmer has posted a beta of Vienna 2.1, an open source            RSS/Atom client for Mac OS X.           &lt;/title&gt;    &lt;content type="xhtml"&gt;      &lt;div xmlns="http://www.w3.org/1999/xhtml"           id="August_1_2006_25279" class="2006-08-01T07:01:19Z"&gt;&lt;p&gt; Steve Palmer has posted a beta of &lt;a shape="rect" href="http://www.opencommunity.co.uk/vienna21.php"&gt;Vienna 2.1&lt;/a&gt;, an open source RSS/Atom client for Mac OS X. Vienna is the first reader I've found acceptable for daily use; not great but good enough. (Of course my standards for "good enough" are pretty high.) 2.1 focuses on improving the user interface with a unified layout that lets you scroll through several articles, article filtering (e.g. read all articles since the last refresh), manual folder reordering, a new get info window,_and_an improved condensed layout.&lt;/p&gt;&lt;/div&gt;    &lt;/content&gt;    &lt;link href="/#August_1_2006_25279"/&gt;    &lt;id&gt;http://www.cafeconleche.org/#August_1_2006_25279&lt;/id&gt;    &lt;updated&gt;2006-08-01T07:01:19Z&lt;/updated&gt;  &lt;/entry&gt;  &lt;entry&gt;    &lt;title&gt;Matt Mullenweg has released Wordpress 2.0.4,            a blog engine based on PHP_and_<U><STRONG><FONT color=#000066>MySQL</FONT></STRONG></U>.          &lt;/title&gt;    &lt;content type="xhtml"&gt;      &lt;div xmlns="http://www.w3.org/1999/xhtml"            id="August_1_2006_21750" class="2006-08-01T06:02:30Z"&gt;&lt;p&gt; Matt Mullenweg has released &lt;a shape="rect" href="http://wordpress.org/development/2006/07/wordpress-204 /"&gt;Wordpress 2.0.4&lt;/a&gt;, a blog engine based on PHP and MySQL. 2.0.4 plugs various security holes, mostly involving plugins.&lt;/p&gt;&lt;/div&gt;    &lt;/content&gt;    &lt;link href="/#August_1_2006_21750"/&gt;    &lt;id&gt;http://www.cafeconleche.org/#August_1_2006_21750&lt;/id&gt;    &lt;updated&gt;2006-08-01T06:02:30Z&lt;/updated&gt;  &lt;/entry&gt;&lt;/feed&gt;</PRE></TD></TR></TBODY></TABLE><BR><>虽然元素名称变了,但用 SimpleXML 处理 Atom 文档的基本方法和 RSS 相同。一个区别是现在请求被命名的元素和本地名称时必须指定名称空间统一资源标识符(URI)。这需要两个步骤:首先通过向 <CODE><FONT face=NSimsun>children()</FONT></CODE> 函数传递名称空间 URI 请求给定名称空间中的孩子元素。然后用那个名称空间中适当的本地名称请求元素。假设第一次把 Atom 提要加载到变量 <CODE><FONT face=NSimsun>$feed</FONT></CODE> 中,如下所示:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$feed = simplexml_load_file('http://www.cafeconleche.org/today.atom');</PRE></TD></TR></TBODY></TABLE><BR><>下面的两行寻找 <CODE><FONT face=NSimsun>title</FONT></CODE> 元素:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >$children =  $feed-&gt;children('http://www.w3.org/2005/Atom');$title = $children-&gt;title;</PRE></TD></TR></TBODY></TABLE><BR><>如果愿意可以将这些代码压缩成一行,虽然行会变得有点长。名称空间中的所有其他元素也必须类似处理。<FONT color=#5c81a7><U>清单 6</U></FONT> 给出了一个完整的 PHP 页面,其中显示带名称空间的 Atom 提要中的标题。</P><BR><B><U><FONT color=#000066>清单 6. 简单的 PHP Atom 标题阅读器</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;?php $feed =  simplexml_load_file('http://www.cafeconleche.org/today.atom');$children =  $feed-&gt;children('http://www.w3.org/2005/Atom');$title = $children-&gt;title;?&gt;&lt;html xml:lang="en" lang="en"&gt;&lt;head&gt;  &lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;&lt;?php echo $title; ?&gt;&lt;/h1&gt;&lt;?php$entries = $children-&gt;entry;foreach ($entries as $entry) {  $details = $entry-&gt;children('http://www.w3.org/2005/Atom');  echo "&lt;h2&gt;" . $details-&gt;title . "&lt;/h2&gt;";}?&gt;&lt;/body&gt;&lt;/html&gt;</PRE></TD></TR></TBODY></TABLE><BR><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_18r1ofd1244a56-1766-47cc-8c77-f1f4492d2506.gif" width="100%"><BR><IMG title=点击图片可在新窗口打开  pointer" height=6 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=8 border=0></TD></TR></TBODY></TABLE><TABLE  cellSpacing=0 cellPadding=0 align=right><TBODY><TR align=right><TD><IMG title=点击图片可在新窗口打开  pointer" height=4 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"><BR><TABLE cellSpacing=0 cellPadding=0 border=0><TBODY><TR><TD vAlign=center><IMG title=点击图片可在新窗口打开  pointer" height=16 alt="" src="http://www.hh010.com/upload_files/article/242/9_bj2ckb4a785081-dfb2-4172-8d02-ce32ab371ff1.gif" width=16 border=0><BR></TD><TD vAlign=top align=right><B><FONT color=#5c81a7><U>回页首</U></FONT></B></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><><U><FONT color=#000066>混合的内容</FONT></U></P><>为什么这个例子中只显示标题行呢?因为在 Atom 中,记录的内容可以包含报道的全部文本:不仅仅是普通文本,还包括标记。这是一种<I>叙述性结构</I>:行中的词句是供人阅读的。和多数的此类数据相似,也有大量的混合内容。于是 XML 就不那么简单了,SimpleXML 方法也开始显示出了一些不足之处。由于不能合理地处理混合内容,这一不足使其在很多应用中被排除了。</P><>可以做到一点,但这不是一个完整的解决方案,只能用于 <CODE><FONT face=NSimsun>content</FONT></CODE> 元素包含真正的 XHTML 的情况。可以使用 <CODE><FONT face=NSimsun>asXML()</FONT></CODE> 函数将这些 XHTML 作为非解析源代码直接复制到输出中,比如:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >echo "&lt;p&gt;" . $details-&gt;content-&gt;asXML() . "&lt;/p&gt;";</PRE></TD></TR></TBODY></TABLE><BR><>生成的结果如<FONT color=#5c81a7><U>清单 7</U></FONT> 所示。</P><BR><B><U><FONT color=#000066>清单 7. asXML 输出</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >   &lt;content type="xhtml"&gt;    &lt;div xmlns="http://www.w3.org/1999/xhtml"         id="August_7_2006_31098" class="2006-08-07T09:38:18Z"&gt;    &lt;p&gt; Nikolai Grigoriev has released &lt;a shape="rect" href="http://www.grigoriev.ru/svgmath"&gt;SVGMath 0.3&lt;/a&gt;, a presentation MathML formatter that produces SVG written in pure Python_and_published under an MIT license. According to Grigoriev, "The new version can work with multiple-namespace documents (e.g. replace all MathML subtrees with SVG in an XSL-FO_or_XHTML document); configuration is made more flexible,_and_several bugs are fixed. There is also a stylesheet to adjust the vertical position of the resulting SVG image in XSL-FO."    &lt;/p&gt;    &lt;/div&gt;  &lt;/content&gt;</PRE></TD></TR></TBODY></TABLE><BR><>这不是纯粹的 XHTML。<CODE><FONT face=NSimsun>content</FONT></CODE> 元素悄悄从 Atom 文档中溜了进来,您真的不愿这样。更糟的是,它的名称空间不对,因此不能被识别。幸运的是,这个多出来的元素实际上没有多大害处,因为 Web 浏览器会忽略不认识的任何标签。完成的文档是无效的,但是关系不大。如果还是觉得别扭,可以通过字符串操作将其去掉,如下所示:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >  $description = $details-&gt;content-&gt;asXML();  $tags = array('&lt;content type="xhtml"'&gt;", "&lt;/content&gt;");  $notags  = array("", "");  $description = str_replace($tags, $notags, $description);</PRE></TD></TR></TBODY></TABLE><BR><>为了使代码更加健壮,可以使用<U><STRONG><FONT color=#000066>正则表达式</FONT></STRONG></U>而不是假定起始标签和前面相同。具体来说,可以考虑各种可能的属性:</P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE >  // end-tag is fixed in form so it's easy to replace  $description = str_replace("&lt;/content&gt;", "", $description);  // remove start-tag, possibly including attributes_and_white space  $description = ereg_replace("&lt;content[^&gt;]*&gt;", "", $description);</PRE></TD></TR></TBODY></TABLE><BR><>即使这样改进之后,代码还是会在注释、处理指令和 CDATA 节上出错。无论怎么分解,恐怕都不会简单了。混合内容实际上超出了 SimpleXML 所能处理的范围。</P><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_18r1ofd1244a56-1766-47cc-8c77-f1f4492d2506.gif" width="100%"><BR><IMG title=点击图片可在新窗口打开  pointer" height=6 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=8 border=0></TD></TR></TBODY></TABLE><TABLE  cellSpacing=0 cellPadding=0 align=right><TBODY><TR align=right><TD><IMG title=点击图片可在新窗口打开  pointer" height=4 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"><BR><TABLE cellSpacing=0 cellPadding=0 border=0><TBODY><TR><TD vAlign=center><IMG title=点击图片可在新窗口打开  pointer" height=16 alt="" src="http://www.hh010.com/upload_files/article/242/9_bj2ckb4a785081-dfb2-4172-8d02-ce32ab371ff1.gif" width=16 border=0><BR></TD><TD vAlign=top align=right><B><FONT color=#5c81a7><U>回页首</U></FONT></B></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><><U><FONT color=#000066>XPath</FONT></U></P><>只要知道文档有什么元素以及在什么位置,<CODE><FONT face=NSimsun>$rss-&gt;channel-&gt;item-&gt;title</FONT></CODE> 这样的表达式很方便。但是,不一定会知道得这么清楚。比方说,在 XHTML 中,标题元素(<CODE><FONT face=NSimsun>h1</FONT></CODE>、<CODE><FONT face=NSimsun>h2</FONT></CODE>、<CODE><FONT face=NSimsun>h3</FONT></CODE> 等等)可以是 <CODE><FONT face=NSimsun>body</FONT></CODE>、<CODE><FONT face=NSimsun>div</FONT></CODE>、<CODE><FONT face=NSimsun>table</FONT></CODE> 或其他几种元素的孩子。此外,<CODE><FONT face=NSimsun>div</FONT></CODE>、<CODE><FONT face=NSimsun>table</FONT></CODE>、<CODE><FONT face=NSimsun>blockquote</FONT></CODE> 及其他元素又可以互相嵌套多次。在很多不那么明确的场合中,使用 <CODE><FONT face=NSimsun>//h1</FONT></CODE> 或 <CODE><FONT face=NSimsun>//h1[contains('Ben')]</FONT></CODE> 这样的 XPath 表达式更方便。SimpleXML 通过 <CODE><FONT face=NSimsun>xpath()</FONT></CODE> 函数支持这种功能。</P><><FONT color=#5c81a7><U>清单 8</U></FONT> 显示的 PHP 页面列出了 RSS 文档中的所有标题,包括提要本身以及每个项的标题。</P><BR><B><U><FONT color=#000066>清单 8. 使用 XPath 查找 title 元素</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > &lt;html xml:lang="en" lang="en"&gt;&lt;head&gt;  &lt;title&gt;XPath Example&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;?php$rss =  simplexml_load_file('http://partners.userland.com/nytRss/nytHomepage.xml');foreach ($rss-&gt;xpath('//title') as $title) {  echo "&lt;h2&gt;" . $title . "&lt;/h2&gt;";}?&gt;&lt;/body&gt;&lt;/html&gt;</PRE></TD></TR></TBODY></TABLE><BR><>SimpleXML 仅支持 XPath 位置路径及位置路径的组合。不支持那些不返回节点集的 XPath 表达式,如 <CODE><FONT face=NSimsun>count(//para)</FONT></CODE> 或 <CODE><FONT face=NSimsun>contains(title)</FONT></CODE>。</P><>从 PHP 5.1 版开始,SimpleXML 可以直接对带名称空间的文档使用 XPath 查询。和通常一样,XPath 位置路径必须使用名称空间前缀,即使搜索的文档使用默认名称空间也仍然如此。<CODE><FONT face=NSimsun>registerXPathNamespace()</FONT></CODE> 函数把前缀和后续查询中使用的名称空间 URL 联系在一起。比方说,如果要查询 Atom 文档中的所有 <CODE><FONT face=NSimsun>title</FONT></CODE> 元素,应使用<FONT color=#5c81a7><U>清单 9</U></FONT> 中所示的代码。</P><BR><B><U><FONT color=#000066>清单 9. 使用 XPath 和名称空间</FONT></U></B><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD ><RE > $atom =  simplexml_load_file('http://www.cafeconleche.org/today.atom');$atom-&gt;registerXPathNamespace('atm', 'http://www.w3.org/2005/Atom');$titles = $atom-&gt;xpath('//atm:title');foreach ($titles as $title) {  echo "&lt;h2&gt;" . $title . "&lt;/h2&gt;";}</PRE></TD></TR></TBODY></TABLE><BR><>最后一点忠告:PHP 中的 XPath 速度非常慢。当改为 XPath 表达式之后页面加载延迟从难以觉察变成了几秒钟,即使是在负荷不高的本地服务器上。如果采用这些技术,必须使用某种缓存技术来获得适当的性能。不可能动态生成每个页面。</P><BR><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=1 alt="" src="http://www.hh010.com/upload_files/article/242/9_18r1ofd1244a56-1766-47cc-8c77-f1f4492d2506.gif" width="100%"><BR><IMG title=点击图片可在新窗口打开  pointer" height=6 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=8 border=0></TD></TR></TBODY></TABLE><TABLE  cellSpacing=0 cellPadding=0 align=right><TBODY><TR align=right><TD><IMG title=点击图片可在新窗口打开  pointer" height=4 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"><BR><TABLE cellSpacing=0 cellPadding=0 border=0><TBODY><TR><TD vAlign=center><IMG title=点击图片可在新窗口打开  pointer" height=16 alt="" src="http://www.hh010.com/upload_files/article/242/9_bj2ckb4a785081-dfb2-4172-8d02-ce32ab371ff1.gif" width=16 border=0><BR></TD><TD vAlign=top align=right><B><FONT color=#5c81a7><U>回页首</U></FONT></B></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><><U><FONT color=#000066>结束语</FONT></U></P><>如果不需要处理混合内容,SimpleXML 对于 PHP 程序员的工具箱来说是个不错新玩意。其适用的情况很多。具体而言,它能够很好地处理简单的、类似记录的数据。只要文档层次不深、不很复杂,而且没有混合内容,SimpleXML 要比使用 DOM 简单得多。如果事先知道文档结构该工具将更有用,虽然通过 XPath 可以满足这种要求。虽然不支持验证和混合内容有点不方便,但不是绝对的。很多简单格式没有混合内容,而且很多应用只涉及到可预知的数据格式。如果符合您的需要,可以自己尝试一下 SimpleXML。只要对错误处理稍加注意,并且通过缓存来解决性能问题,SimpleXML 可以成为 PHP 中一种可靠、健壮的 XML 处理方法。</P><BR><BR><><U><FONT color=#000066>参考资料 </FONT></U></P><B>学习</B><BR><UL><LI>您可以参阅本文在 developerWorks 全球网站上的 <FONT color=#5c81a7><U>英文原文</U></FONT>。<BR><BR><LI><FONT color=#5c81a7><U>SimpleXML 的官方文档</U></FONT>:仔细阅读 PHP 版本 5 用户手册,了解这个将 XML 转换成对象以便用一般属性选择器和数组迭代器处理的工具集。<BR><BR><LI><I><FONT color=#5c81a7><U>XML in a Nutshell</U></FONT></I>(Elliotte Rusty Harold 和 W. Scott Means,O'Reilly,2005):该书集中介绍了 XML,请深入阅读关于 XML 和 XPath 的内容。 <BR><BR><LI>“<FONT color=#5c81a7><U><STRONG><FONT color=#000066>Ajax</FONT></STRONG></U> RSS reader</FONT></A>”(Jack D. Herrington,developerWorks,2006 年 5 月):讨论了在 PHP 中使用<U><STRONG><FONT color=#000066>数据库</FONT></STRONG></U>、JavaScript 代码以及 DOM 编写 RSS 的一种高级方法。<BR><BR><LI>“<FONT color=#5c81a7><U>An overview of the Atom version 1.0 Syndication Format</U></FONT>”(James Snell,developerWorks,2005 年 8 月):讨论了 Atom 与其他联合格式相比在技术上的优势,并通过几个典型的例子加以说明。 <BR><BR><LI><FONT color=#5c81a7><U>IBM XML 认证</U></FONT>:看看如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。<BR><BR><LI><FONT color=#5c81a7><U>XML 技术库</U></FONT>:developerWorks XML 专区提供了大量<U><STRONG><FONT color=#000066>技术文章</FONT></STRONG></U>和技巧、<U><STRONG><FONT color=#000066>教程</FONT></STRONG></U>、标准以及 IBM 红皮书。 <BR><BR><LI>随时关注<FONT color=#5c81a7><U>developerWorks 技术事件和</U><STRONG><U><FONT color=#000066>网络</FONT></U></STRONG>广播</FONT></A>。<BR><BR></LI></UL><BR><B>获得产品和技术</B><BR><UL><LI>使用<FONT color=#5c81a7><U>IBM 试用软件</U></FONT>:构建您的下一个项目,可直接从 developerWorks 下载。<BR><BR></LI></UL><BR><B>讨论</B><BR><UL><LI><FONT color=#5c81a7><U>XML 专区讨论</U><STRONG><U><FONT color=#000066>论坛</FONT></U></STRONG>(英文)</FONT></A>:参与任何一个面向 XML 的论坛。<BR><BR><LI><FONT color=#5c81a7><U>developerWorks blogs</U></FONT>:加入 developerWorks 社区。</LI></UL><BR><BR><><U><FONT color=#000066>关于作者</FONT></U></P><TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TBODY><TR><TD colSpan=3><U><FONT color=#000066><IMG title=点击图片可在新窗口打开  400px; CURSOR: pointer" height=5 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width="100%"></FONT></U></TD></TR><TR vAlign=top align=left><TD><><U><FONT color=#000066></FONT></U></P></TD><TD><U><FONT color=#000066><IMG title=点击图片可在新窗口打开  pointer" height=5 alt="" src="http://www.hh010.com/upload_files/article/242/9_1qsp2i32cc0b58-f5cf-4d0c-92da-f21df69b56a6.gif" width=4></FONT></U></TD><TD width="100%"><>Elliotte Rusty Harold 来自新奥尔良, 现在他还定期回老家喝一碗美味的秋葵汤。不过目前,他和妻子 Beth 定居在纽约临近布鲁克林的 Prospect Heights,同住的还有他的猫咪 Charm(取自夸克)和 Marjorie(取自他岳母的名字)。他是 Polytechnic 大学计算机科学的副教授,他在该校讲授 Java 和面向对象编程。他的 Web 站点 <FONT color=#5c81a7><U>Cafe au Lait</U></FONT> 已经成为 <U><STRONG><FONT color=#000066>Internet</FONT></STRONG></U> 上最流行的独立 Java 站点之一,它的姊妹站点 <FONT color=#5c81a7><U>Cafe con Leche</U></FONT> 已经成为最流行的 XML 站点之一。他的书包括 <I><FONT color=#5c81a7><U>Effective XML</U></FONT></I>、<FONT color=#5c81a7><U><I>rocessing XML with Java</I></U></FONT>、<FONT color=#5c81a7><U><I>Java Network Programming</I></U></FONT> 和 <I><FONT color=#5c81a7><U>The XML 1.1 Bible</U></FONT></I>。他目前在从事处理 XML 的 <FONT color=#5c81a7><U>XOM</U></FONT> API、<FONT color=#5c81a7><U>Jaxen</U></FONT> XPath 引擎和 <FONT color=#5c81a7><U>Jester</U></FONT> 测试覆盖率工具的开发工作。</P></TD></TR></TBODY></TABLE>
发表于 2012-4-25 23:26:02 | 显示全部楼层
沙发 2012-4-25 23:26:02 回复 收起回复
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2024-4-27 06:29 , Processed in 0.058435 second(s), 10 queries , Redis On.  

  Powered by Discuz!

  © 2001-2024 HH010.COM

快速回复 返回顶部 返回列表