手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表Tag:xml

php simplexmlElement 操作xml的命名空间

这是今天中午发生的事情,有人在群里求助,比如xml中如果标记是<xx:xxxx>content</xx:xxxx>这样的情况下,取不到 xx:xxxx 为下标的值。
看了这个问题,第一个反应就是namespace的关系,但我从来没有使用simplexml操作过namespace,于是就翻开手册查了一下资料,问题并没有解决,最终是通过google解决了该问题。

提问题的朋友贴出了数据源,来自于:http://code.google.com/intl/zh-CN/apis/contacts/docs/3.0/developers_guide_protocol.html#retrieving_without_query,数据结构大致如下:

XML/HTML代码
  1. <feed xmlns='http://www.w3.org/2005/Atom'      xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'      xmlns:gContact='http://schemas.google.com/contact/2008'      xmlns:batch='http://schemas.google.com/gdata/batch'      xmlns:gd='http://schemas.google.com/g/2005'      gd:etag='W/"CUMBRHo_fip7ImA9WxRbGU0."'>      
  2.     <id>liz@gmail.com</id>      
  3.     <updated>2008-12-10T10:04:15.446Z</updated>      
  4.     <category scheme='http://schemas.google.com/g/2005#kind'      term='http://schemas.google.com/contact/2008#contact' />      
  5.     <title>Elizabeth Bennet's Contacts</title>      
  6.     <link rel='http://schemas.google.com/g/2005#feed'      type='application/atom+xml'      href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full' />      
  7.     <link rel='http://schemas.google.com/g/2005#post'      type='application/atom+xml'      href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full' />      
  8.     <link rel='http://schemas.google.com/g/2005#batch'      type='application/atom+xml'      href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full/batch' />      
  9.     <link rel='self' type='application/atom+xml'      href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full?max-results=25' />      
  10.     <author>        
  11.         <name>Elizabeth Bennet</name>        
  12.         <email>liz@gmail.com</email>      
  13.     </author>      
  14.     <generator version='1.0' uri='http://www.google.com/m8/feeds'>      Contacts    </generator>      
  15.     <openSearch:totalResults>1</openSearch:totalResults>      
  16.     <openSearch:startIndex>1</openSearch:startIndex>      
  17.     <openSearch:itemsPerPage>25</openSearch:itemsPerPage>      
  18.     <entry gd:etag='"Qn04eTVSLyp7ImA9WxRbGEUORAQ."'>        
  19.         <id>        http://www.google.com/m8/feeds/contacts/liz%40gmail.com/base/c9012de      </id>        
  20.         <updated>2008-12-10T04:45:03.331Z</updated>        
  21.         <app:edited xmlns:app='http://www.w3.org/2007/app'>2008-12-10T04:45:03.331Z</app:edited>        
  22.         <category scheme='http://schemas.google.com/g/2005#kind'        term='http://schemas.google.com/contact/2008#contact' />        
  23.         <title>Fitzwilliam Darcy</title>        
  24.         <gd:name>          
  25.             <gd:fullName>Fitzwilliam Darcy</gd:fullName>        
  26.         </gd:name>        
  27.         <link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'        href='https://www.google.com/m8/feeds/photos/media/liz%40gmail.com/c9012de'        gd:etag='"KTlcZWs1bCp7ImBBPV43VUV4LXEZCXERZAc."' />        
  28.         <link rel='self' type='application/atom+xml'        href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full/c9012de' />        
  29.         <link rel='edit' type='application/atom+xml'        href='https://www.google.com/m8/feeds/contacts/liz%40gmail.com/full/c9012de' />        
  30.         <gd:phoneNumber rel='http://schemas.google.com/g/2005#home'        primary='true'>        456      </gd:phoneNumber>        
  31.         <gd:extendedProperty name='pet' value='hamster' />        
  32.         <gContact:groupMembershipInfo deleted='false'        href='http://www.google.com/m8/feeds/groups/liz%40gmail.com/base/270f' />      
  33.     </entry>    
  34. </feed>  

这个结构在上面的地址里有,这个是我格式化过的XML数据,现在要取得类似于“<gd:phoneNumber rel='http://schemas.google.com/g/2005#home'        primary='true'>        456      </gd:phoneNumber> ”中的值。

最终代码如下:

PHP代码
  1. $x = new SimpleXmlElement($str);  
  2. foreach($x->entry as $t){  
  3.     echo $t->id . "<br >";  
  4.     echo $t->updated . "<br />";  
  5.     $namespaces = $t->getNameSpaces(true);  
  6.     $gd = $t->children($namespaces['gd']);   
  7.     echo $gd->phoneNumber;  
  8. }  

当然,如果不象上面这样写,也可以写成这样:

PHP代码
  1. $x = new SimpleXmlElement($str);  
  2. foreach($x->entry as $t){  
  3.     echo $t->id . "<br >";  
  4.     echo $t->updated . "<br />";  
  5.     //$namespaces = $t->getNameSpaces(true);  
  6.     //注意这里与上面一段的区别  
  7.     $gd = $t->children('http://schemas.google.com/g/2005');   
  8.     echo $gd->phoneNumber;  
  9. }  

只是象第二种写法就属于硬编码了,这样不太好,万一哪天有变化,还得再更改N多代码。
问题接踵而来,比如象下面这段:

XML/HTML代码
  1. <event:event>   
  2. <event:sessionKey></event:sessionKey>   
  3. <event:sessionName>Learn QB in Minutes</event:sessionName>   
  4. <event:sessionType>9</event:sessionType>   
  5. <event:hostWebExID></event:hostWebExID>   
  6. <event:startDate>02/12/2009</event:startDate>   
  7. <event:endDate>02/12/2009</event:endDate>   
  8. <event:timeZoneID>11</event:timeZoneID>   
  9. <event:duration>30</event:duration>   
  10. <event:description></event:description>   
  11. <event:status>NOT_INPROGRESS</event:status>   
  12. <event:panelists></event:panelists>   
  13. <event:listStatus>PUBLIC</event:listStatus>   
  14. </event:event>  

这种非标准的XML,没有定义命名空间,怎么办?在这种情况下,其实SimpleXmlElement就已经直接可以解决了,但是会报warnging,因为他认为event这个命名空间不存在。
解决方法是:

PHP代码
  1. $xml = @new SimpleXmlElement($str);//在前面加@抑止错误。  
  2. echo "<pre>";  
  3. print_r($xml);  

目前看来,这种解决方法比较好。

Tags: php, simplexml, xml, namespace