taoCMS是基于php+sqlite/mysql的国内最小(100Kb左右)的功能完善、开源免费的CMS管理系统

使用php函数simplexml_load_file 解析带有cdata的xml

2013-05-02
在XML文档中使用类似"<" 的字符, 那么解析器将会出现错误,因为解析器会认为这是一个新元素的开始,组合XML字符串时遇到了< 。需要转义。
PHP5自带的simplexml_load_file对这个xml解析内容为空是因内容里包含:
<![CDATA[标题3]]> 内容里有 <> 特殊字符,所以,解析不到值。

又是一个鸡肋,为什么要说又呢?呵呵。

XML 的 CDATA,即 <![CDATA[ 与 ]]> 之间可以放 <、>、&、'、" 字符,由于 CDATA 中的内容不会被解析,所以上述字符在 CDATA 中不会造成 XML 的错误,否则“<”会被当作一个标签的开始。

但是,重要了。CDATA 中仍然不能放一些东西:

一是放特殊符号危险,比如“”,可能某些解析器认识,某些解析器不认识,解决办法:XmlTextReader 解析 XML 时遇到特殊字符出错。
二是不能放 <![CDATA[ 和 ]]>。像我们的 IT 类文章中可能经常出现这些字符,出现了,若写在 XML 势必出错,解决办法是用 System.Web.HttpUtility.HtmlEncode 将 <、>、&、'、" 进行编码,取值时再解码。那问题来了,既然已经编码了,还要 CDATA 做什么?


最后,在一个兄弟那儿看到是支持CDATA的PHP也可以解析,如下:
http://hi.baidu.com/yinqinlong502/item/e4dfc900a977ed1acc34eae9
php 解析xml遇到cdata怎么办
用$rss = simplexml_load_file ( '11111.xml', 'SimpleXMLElement', LIBXML_NOCDATA );哎就为了这么个函数我还去写正则准备替换了,白白废了我两小时,shit!!!以后多注意下那些函数的可选参数吧。长点教训.
直接输入xml内容为参数的也支持CDATA的解析,如下:
view plainprint?
$rss = simplexml_load_file ( '11111.xml', 'SimpleXMLElement', LIBXML_NOCDATA );
$xmlCode = simplexml_load_string($this->xmlContents, 'SimpleXMLElement', LIBXML_NOCDATA);



需要解析的XML格式为:
实践如下:
xml文件:
view plainprint?
<?xml version="1.0" encoding="utf-8"?>
<DATAS>

<DATA>
<TITLE><![CDATA[标题3]]></TITLE>
<URL><![CDATA[http://dinshiju.cntv.cn]]></URL>
<THUMB><![CDATA[http://p2.img.cctvpic.com/photoAlbum/page/performance/img/2013/1/14/1358132785557_460.jpg]]></THUMB>
</DATA>

<DATA>
<TITLE><![CDATA[标题2]]></TITLE>
<URL><![CDATA[http://www.cntv.cn]]></URL>
<THUMB><![CDATA[http://p1.img.cctvpic.com/photoAlbum/page/performance/img/2013/1/14/1358132556020_927.jpg]]></THUMB>
</DATA>

<DATA>
<TITLE><![CDATA[标题1]]></TITLE>
<URL><![CDATA[http://baidu.com]]></URL>
<THUMB><![CDATA[http://p5.img.cctvpic.com/photoAlbum/page/performance/img/2013/1/14/1358132536506_532.jpg]]></THUMB>
</DATA>

</DATAS>


解析PHP代码,仅仅对当前的xml做解析:
view plainprint?
<?php
function cdataXML2Arr($parseXmlsUrl){
header("Content-Type: text/html; charset=UTF-8");
$xmldata = simplexml_load_file ( $parseXmlsUrl, 'SimpleXMLElement', LIBXML_NOCDATA );

$arrayData = array();
$outArr = array();
$listcount = count($xmldata->DATA);
for($i=0;$i<$listcount;$i++){ //第二部分,直接把 $xml 对象转换为数组。
$title = (array)$xmldata->DATA[$i]->TITLE;
$url = (array)$xmldata->DATA[$i]->URL;
$thumb= (array)$xmldata->DATA[$i]->THUMB;
$arrayData = array('TITLE'=>$title[0],'URL'=>$url[0],'THUMB'=>$thumb[0]);//取数组第0键值
$outArr[] = $arrayData;
}
return $outArr;
}
//test cdata function
$parseXmlsUrl = "http://localhost/aaa/index.xml";
$xmlsArr = cdataXML2Arr($parseXmlsUrl);
print_r($xmlsArr);
?>


进一步写成类更加宽泛的适应调用(部门之间有不遵守xml规范的,有的返回的xml第一行换行了需要先去掉之才能传入php函数中去解析正常,这就是在中国的实际开发情况。)该类可以直接传入xml格式内容,也可以直接输入xml的路径或则url进行解析:
view plainprint?
<?php
//输出UTF8编码
header("Content-Type: text/html; charset=UTF-8");
?>

<?php //直接传入xml内容转为数组的XML类调用方法
$xmlFileOrxmlUrl = 'http://dianshiju.cntv.cn/dianshiju/xml/index.xml';
$xmlContents = file_get_contents($xmlFileOrxmlUrl);

$xmlToArrObj = new XmlToArr($xmlContents);
//直接传入xml格式数据
$xmlToArrResult = $xmlToArrObj -> getxmlToArrResult();
print_r($xmlToArrResult);
?>

<?php //传入xml文件路径转为数组的XML类调用方法
$xmlFileOrxmlUrl = 'http://dianshiju.cntv.cn/dianshiju/xml/index.xml';
$xmlToArrObj = new XmlToArr($xmlFileOrxmlUrl, "xmlUrlOrPath");
$xmlToArrResult = $xmlToArrObj -> getxmlToArrResult();
print_r($xmlToArrResult);
?>

<!--下面是这个解析Xml类的实体,可以单独分开并包含供上面函数调用。-->
<?php
/**
* 将xml转为数组类
*参数:文件地址或者Url地址
*返回:该xml的Url地址转为数组相关情况
* @author jackxiang
* @version 12692 2013-01-17 10:46:04Z jackxiang $
*/
class XmlToArr {
//xml文件或url
public $xmlFileOrxmlUrl = "";

//xml内容 (需要经过过滤等)
public $xmlContents = "";

//xml转成的数组的结果
public $xmlToArrResult = array();

//读取文件超时时间设置(默认3秒)
public $timeOut = 3;

public function xmlToArr($xmlContentsOrxmlFileUrl, $inputType = "xmlcontents", $timeOut = 3) {
if ($inputType == "xmlcontents") {//输入的是xml内容
$this -> xmlContents = $xmlContentsOrxmlFileUrl;
//直接赋值给类里的xml内容
} else {//xmlUrlOrPath:输入的是xml地址或则Url形式
$xmlFileOrxmlUrl = $xmlContentsOrxmlFileUrl;
//是Url或则本地文件
$this -> xmlFileOrxmlUrl = $xmlFileOrxmlUrl;
//文件句柄或则Url传入类变量
$this -> timeOut = $timeOut;
//设置读取xml文件的超时时间
$this -> vita_get_url_content();
//获取xml文件内容

}
$this -> filterXmlContents();
//过滤掉不符合xml规则的 刚开始就换行等去掉
$this -> transXmlToArr();
//把xml内容转成数组
}

public function filterXmlContents() {//对xml里的相关字符做过滤
$this -> xmlContents = str_replace(array("r", "n"), "", $this -> xmlContents);
//去掉空字符及换行等空字符
}

//获取数据兼容file_get_contents与curl
public function vita_get_url_content() {
if (function_exists('file_get_contents')) {
$ctx = stream_context_create(array('http' => array('timeout' => $this -> timeOut)));
$this -> xmlContents = @file_get_contents($this -> xmlFileOrxmlUrl, 0, $ctx);
if (strlen($this -> xmlContents) == 0) {
die("文件:" . __FILE__ . "行:" . __LINE__ . "XML文件读取失败或其返回为空,请检查!");
}
} else {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this -> xmlFileOrxmlUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this -> timeOut);
$file_contents = curl_exec($ch);
curl_close($ch);
}
return $this -> xmlContents;
}

//解析xml函数
public function transXmlToArr() {
$xml_parser = xml_parser_create();
//首先初步检查是否是xml格式
if (xml_parse($xml_parser, $this -> xmlContents, true)) {
xml_parser_free($xml_parser);
//释放掉判断的句柄
$xmlCode = simplexml_load_string($this -> xmlContents, 'SimpleXMLElement', LIBXML_NOCDATA);
$this -> xmlToArrResult = $this -> get_object_vars_final($xmlCode);
} else {//不符合xml基本格式
$this -> xmlToArrResult = '';
die("文件:" . __FILE__ . "行:" . __LINE__ . "数据结构分析不是xml格式,请检查。");
}
}

public function get_object_vars_final($obj) {
if (is_object($obj)) {
$obj = get_object_vars($obj);
}
if (is_array($obj)) {
foreach ($obj as $key => $value) {
$obj[$key] = $this -> get_object_vars_final($value);
}
}
return $obj;
}

public function getxmlToArrResult() {
return $this -> xmlToArrResult;
//返回转化成的数组
}

};
?>

更多参考:
http://www.cnblogs.com/songsh96/archive/2007/07/10/812126.html
http://hi.baidu.com/nicelinda/item/37e13d8cb820fec8b17154ac
http://www.php100.com/manual/w3school/xml/xml_cdata.asp.html

类别:技术文章 | 阅读:396689 | 评论:0 | 标签:xml php simplexml

想收藏或者和大家分享这篇好文章→

“使用php函数simplexml_load_file 解析带有cdata的xml”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

taoCMS发布taoCMS 3.0.2(最后更新21年03月15日),请大家速速升级,欢迎大家试用和提出您宝贵的意见建议。

捐助与联系

☟请使用新浪微博联系我☟

☟在github上follow我☟

标签云