Chad 2010-06-10

今天有个任务是要用PHP5来对比两个XML文件的内容。在PHP5里处理XML文件可以用DOM,但是对于简单的处理,用SimpleXML则更为简便。

可是,这次用以下代码读出来的文件,子节点的内容全是空的:

Code - PHPPlain Text
 
  1. $sourceFileContent = file_get_contents($sourceFileName);  
  2. $sourceXML = new SimpleXMLElement($sourceFileContent);  
  3. var_dump($sourceXML);  

但是elements的attributes却可以读取到,这是为什么呢?我一看XML文件的内容,发现所有的elements的内容都用<![CDATA[ ]]>包起来了,也就是说,都标识成为CData1了。可以看出SimpleXML在parse XML文件内容时,把CData里的内容全都忽略了。

这该怎么处理呢?用正则表达式把CData标识去掉——这是我的第一反应。

但是,我又想,这种事情应该不会没有前人遇到过吧?为了不要“重复发明车轮”,我决定先搜搜资料。结果在PHP.net上给我找到了一个处理办法2

Code - XML/HTMLPlain Text
 
  1. // nathan at gimpstraw dot com  
  2. //05-Apr-2008 05:43  
  3. //I'm using SimpleXML to process data sent back from an API request, and I ran into the CDATA problem and the error you get from html entities, and here is a solution i came up with, don't know if it's the most practical, but it's working.  
  4.   
  5. <?php  
  6. $str = <<< XML  
  7. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
  8. <menu>  
  9.     <item>  
  10.         <title><![CDATA[Café]]></title>  
  11.         <description><![CDATA[Some description.]]></description>  
  12.     </item>  
  13. </menu>  
  14. XML;  
  15.   
  16. $str = preg_replace("/\<\!\[CDATA\[(.*?)\]\]\>/ies", "'[CDATA]'.base64_encode('$1').'[/CDATA]'", $str);  
  17. $xml = new SimpleXMLElement($str);  
  18.   
  19. // Return item title's  
  20. foreach ($xml->item as $item) {  
  21.     $tmp = (string) $item->title;  
  22.     $tmp = preg_replace("/\[CDATA\](.*?)\[\/CDATA\]/ies", "base64_decode('$1')", $tmp);  
  23.     echo $tmp;  
  24. }  
  25. ?>  

真好。。。又不用自己写了。。。就这样又解决了一个问题。。。

 

1. CData, http://en.wikipedia.org/wiki/CDATA_section

2. SimpleXML Functions, http://php.net/manual/en/ref.simplexml.php