php7实践指南-ch17PHP处理XML和JSON

XML是一种数据的表现形式,在信息交换和传递中起到非常重要的作用,比如在微信公众账号的开发中,开发者服务器接收和向用户发送消息都使用XML作为数据的公用格式。许多语言都支持对XML的操作处理,PHP借助一些扩展也可以实现对XML的操纵。XML和HTML类似,都使用“<”和“>”括起来的标签来标记文本,所不同的是XML更为灵活,你可以自主定义标签,而不必像HTML那样要使用诸如<a> <img>等一些规定的标签。

17.1 生成XML

17.1.1 由字符串或数组遍历生成XML

由字符串或数组遍历生成XML是最简单的生成XML的方式。请看下面两个例子。

1.使用字符串生成XML

代码如下:

<?php
header('Content-Type:text/xml');
$xmlstr=<<<XML
<?xml version="1.0" standalone='yes' ?>
<movies>
    <movie>
        <title>PHP:Behind the Parser</title>
        <characters>
            <character>
                <name>Ms.Coder</name>
                <actor>Onlivia Actora</actor>
            </character>
            <character>
                <name>Ms.Coder</name>
                <actor>E1 Act#211;r</actor>
            </character>
        </characters>
        <plot>
        So,this language. It's like a programming language. Or is it a 
        scriptinng language? All is revealed in this thrilling horror spoof
        of a documentary.
        </plot>
        <great-lines>
            <line>PHP solves all my web problems</line>
        </great-lines>
        <rating type="thumbs">7</rating>
        <rating type="stars">5</rating>
    </movie>
</movies>
XML;
echo $xmlstr;
?>

只需在字符串中定义XML的格式即可,这种是最简单的生成XML的方式。对于需要生成固定格式的XML形式的字符串,可以将其写成一个方法,替换其中的变量即可。

2.使用数组循环遍历生成XML

使用字符串生成XML虽然简单,但是如果在一个XML中有多个相同标签的内容,比如<movies>标签中有多个<movie>子标签则需要写很长的字符串才行,如果能使用数组遍历生成这种XML就可以省写许多代码。在很多情况下,我们也需要实现数组和XML数据格式之间的转换,使用数组循环遍历生成XML的代码示例如下:

<?php
header('Content-Type:text/xml');
echo '<?xml version="1.0" standalone=\'yes\' ?>'."\n";
echo "<books>\n";

$books=array(
        array('bookname'=>'微信公众平台开发实践与应用案例',
               'author' =>"陈小龙",
                'press' =>"清华大学出版社",
                'publishtime'=>'2016-07'
             ),
        array(
            'bookname'=>'php快速开发入门o2o网站和app后台开发',
            'author' =>"陈小龙",
            'press' =>"清华大学出版社",
            'publishtime'=>'2017-07'
            )
);

foreach ($books as $book){
    echo "<book>\n";
    foreach ($book as $tag=>$value){
        echo "<$tag>".htmlspecialchars($value)."</$tag>\n";
    }
    echo "</book>";
}
echo "</books>";

保存并执行以上代码的输出结果如下:

17.1.2 通过DOM生成XML

通过DOM扩展来创建一个DOMDocument对象,创建完之后可调用DOMDocument::save()或者DOMDocument::saveXML()方法生成标准格式的XML文档,代码示例如下:

<?php
header('Content-Type:text/xml');
//创建DOMDocument对象并设置XML版本为1.0,编码为utf-8
$dom = new DOMDocument('1.0','utf-8');
//创建一个根元素,并将其添加到文档
$book = $dom->appendChild($dom->createElement('book'));

//创建一个bookname元素,并将其添加到$book
$bookname = $book->appendChild($dom->createElement('bookname'));

//设置bookname元素中的文本
$bookname->appendChild(($dom->createTextNode("微信公从平台开发实战与应用案例")));

$author= $book->appendChild($dom->createElement('author'));
$author->appendChild($dom->createTextNode('陈小龙'));
//设置author中的属性和值
$author->setAttribute("age",'22 years old');

$press = $book->appendChild($dom->createElement('press'));
$press->appendChild($dom->createTextNode('清华大学出版社'));

$publishtime=$book->appendChild($dom->createElement('publishtime'));
$publishtime->appendChild($dom->createTextNode('2016-07'));

//格式化XML数据
$dom->formatOutput=true;
echo $dom->saveXML();


保存并执行以上代码,得到的XML结果为:

<?xml version="1.0" encoding="utf-8"?>
<book>
  <bookname>微信公从平台开发实战与应用案例</bookname>
  <author age="22 years old">陈小龙</author>
  <press>清华大学出版社</press>
  <publishtime>2016-07</publishtime>
</book>

在一个XML文档中需要明确4个概念:树、元素、节点、属性和值。在上面的XML数据中,我们可称一个XML文档为一个XML文档树,例子中<book>、<bookname>、<author>、<press>、<publishtime>可称为元素,而“微信公众平台开发实战与应用案例”“清华大学出版社”等可称为节点,“age”可称为属性,“22 years old”为“age”属性的值。在创建元素之前,需要先创建一个新文档对象,并传递一个版本号和编码作为参数,然后使用createElement()方法创建元素。要创建文档的根元素,必须将$book作为$dom文档对象的子元素添加进来。所有的元素都是使用$dom对象的createElement()方法创建,在创建元素后,可以将该元素作为树中任何元素的子元素,使用该元素调用appendChild()方法决定了其在树中的位置。

在<author></author>内部添加文本内容,需要先用createTextNode()创建一个节点,然后把该节点添加到$author。要添加属性,就在元素上调用setAttribute()方法,并传递属性的名和值作为参数。除了使用saveXML()可将xml保存并输出外,还可使用save('name.xml')函数将其保存为一个文件。在默认情况下生成的xml输出都会放在长长的一行,不包含任何的空格、缩进和换行,设置formatOutput值为true即可格式化XML数据。

17.1.3 通过PHP SimpleXML生成XML

使用SimpleXML也可生成XML,比使用DOM更加简单,示例代码如下:

<?php
header('Content-Type:text/xml');
$string = <<<XML
<?xml version='1.0' encoding='utf-8' ?>
<dom></dom>
XML;
//载入XML字符串,将其转换成对象
$book = simplexml_load_string($string);
//创建元素并设置对应文本内容
$book->addChild('bookname','微信公众平台开发实战与应用案例');
$author=$book->addChild('author','陈小龙');
//设置元素的属性值
$author->addAttribute('age','22 years old');
$book->addChild('press','清华大学出版社');
$book->addChild('publishtime','2016-07');
echo $book->asXML();
?>

17.2 解析XML

我们可通过DOM和SimpleXML创建XML数据,同样可使用这两种方式解析XML,这一节就来介绍如何获取XML数据中的节点属性和值。

17.2.1 通过DOM解析XML

通过DOM可生成XML,同样也可使用DOM来解析XML,代码示例如下:

<?php
//使用系统默认异常错误处理机制
ini_set('display_errors',1);            //错误信息
ini_set('display_startup_errors',1);    //php启动错误信息
error_reporting(-1);                    //打印出所有的 错误信息
ini_set('error_log', dirname(__FILE__) . '/error_log.txt'); //将出错信息输出到一个文本文件

//header('Content-Type:text/xml');
$xmlstr=<<<XML
<?xml version="1.0" standalone='yes' ?>
<movies>
    <movie a='aa'>
        <title>PHP:Behind the Parser</title>
        <characters>
            <character>
                <name age='22 years old' country='china'>Ms.Coder</name>
                <actor>Onlivia Actora</actor>
            </character>
            <character>
                <name>Ms.Coder</name>
                <actor>E1 Act#211;r</actor>
            </character>
        </characters>
        <plot>
        So,this language. It's like a programming language. Or is it a 
        scriptinng language? All is revealed in this thrilling horror spoof
        of a documentary.
        </plot>
        <great-lines>
            <line>PHP solves all my web problems</line>
        </great-lines>
        <rating type="thumbs">7</rating>
        <rating type="stars">5</rating>
    </movie>
</movies>
XML;
//echo $xmlstr;

$dom = new DOMDocument();
$dom->loadXML($xmlstr);

//获取标签<character>,并循环获得子元素的节点内容
$movie=$dom->getElementsByTagName('character');
foreach($movie as $key=>$value){
    $name=$value->getElementsByTagname('name');
    echo $name->item(0)->firstChild->nodeValue."<br/>"; //firstChild元素第一个子节点,nodeValue其中的值
}

//获得属性值
$attr=$dom->getElementsByTagName('character')[0]->getElementsByTagName('name')->item(0)->attributes;
foreach ($attr as $key=>$value){
    echo $key,":",$value->value,'<br/>';
}

//使用getAttribute获得属性值
$age=$dom->getElementsByTagName('character')[0]->getElementsByTagName('name')->item(0)->getAttribute('age');
echo $age;

仔细阅读例子中的代码,首先实例化DOMDocument对象,使用loadXML()方法载入一段字符串,DOMDocument类还提供load()方法载入一个外部xml文件。getElementsByTagname()方法可用来根据标签名称获得其元素对象。在本例中,有两个<character>标签,所以使用foreach循环获得子元素<name>标签,而在一个<character>标签里可能会有多个<name>标签,所以使用item(0)指定获得的是<character>内部的第一个<name>标签,以此类推,可使用item(1)获取第二个<name>标签、item(2)获取第三个<name>标签。在本例中,每个<character>标签内只有一个<name>标签。firstChild()表示该元素的第一个子节点,nodeValue便是其中的值。

使用DOM的优势在于,其遵循W3C规范,许多语言都以差不多相同的方式实现DOM函数。这样就减少了在不同语言间处理XML的转换时间。DOM规范庞大且复杂,本例只是演示了常见的处理xml的一般方式,关于DOM的更多信息可到http://www.w3.org/DOM/查看。

17.2.2 通过PHP SimpleXML解析XML

SimpleXML是用来处理XML最便捷的方案,简化了与XML的交互,可以把元素转换成对象属性,位于标签之间的文本被指定给属性。如果同一个位置上有多个同名元素,那么这些元素会被放在一个列表中。元素的属性会被转换成数组元素,其中数组的键是属性名,键的值就是属性的值。下面用一个例子来说明SimpleXML的用法。

<?php
//使用系统默认异常错误处理机制
ini_set('display_errors',1);            //错误信息
ini_set('display_startup_errors',1);    //php启动错误信息
error_reporting(-1);                    //打印出所有的 错误信息
ini_set('error_log', dirname(__FILE__) . '/error_log.txt'); //将出错信息输出到一个文本文件

//header('Content-Type:text/xml');
$xmlstr=<<<XML
<?xml version="1.0" standalone='yes' ?>
<movies>
    <movie a='aa'>
        <title>PHP:Behind the Parser</title>
        <characters>
            <character>
                <name age='22 years old' country='china'>Ms.Coder</name>
                <actor>Onlivia Actora</actor>
            </character>
            <character>
                <name>Ms.Coder</name>
                <actor>E1 Act#211;r</actor>
            </character>
        </characters>
        <plot>
        So,this language. It's like a programming language. Or is it a 
        scriptinng language? All is revealed in this thrilling horror spoof
        of a documentary.
        </plot>
        <great-lines>
            <line>PHP solves all my web problems</line>
        </great-lines>
        <rating type="thumbs">7</rating>
        <rating type="stars">5</rating>
    </movie>
</movies>
XML;
$sx=simplexml_load_string($xmlstr);
echo $sx->movie->title;
echo ":";
echo $sx->movie->characters->character[0]->name.":";
echo $sx->movie->rating[1]['type'];

保存并执行以上程序的结果为:PHP: Behind the Parser:Ms. Coder:stars。

除了使用simplexml_load_string()载入一个XMl字符串,也可以使用simplexml_load_file()来载入一个外部XML文本文件。如果你想改变解析的XML的指定节点文本,可以直接为其赋值,比如将第一个<character>中的<name>节点文本由Mr.Coder改为Miss.Code就可以直接使用$sx->movie->characters->character[0]->name='Miss.Code’重新赋值。

17.3 json的使用

json是一种轻量级的数据交换格式,在网络交互中使用的非常广泛,几乎所有的编程语言,都支持创建和读取json数据。json的语法规则如下:

(1)数据在键值对中

(2)数据由逗号分隔

(3)花括号保存对象

(4)方括号保存数组

JSON格式的数据使用范围很广,互联网上定义的各种接口规范基本都是以JSON的形式存在,PHP作为一门服务端语言也常被用来写服务端接口逻辑,向客户端返回JSON格式的数据。相对来说,在很多语言中处理json数据都比处理xml数据要简单得多,json数据和数组可以实现非常方便的转换,在包含同样信息的情况下,json数据字节数比xml要少很多,json的这种便捷性和简洁性使其可以取代xml成为互联网信息传输的规范数据格式。PHP用json_encode和json_decode来实现这种转换。

1. json_encode

json_encode可将数组转成json编码数据,语法如下:

function json_encode ($value, $options = 0, $depth = 512) false|string

关于json_encode的例子如下:

<?php
echo "连续数组";
$sequential = array("foo","bar","baz","blong");
echo json_encode($sequential);
echo "<br/>非连续数组";
$onnsequential =array(1=>"foo",2=>"bar",3=>"baz",4=>"blong");
echo json_encode($onnsequential);
echo "<br/>删除一个连续数组的方式产生的非连续数组";
unset($sequential[1]);
echo json_encode($sequential);
echo"<br/>二维数组";
$arr = array(array('name'=>'chenxiaolong'),array('name'=>'chenxiaolong'));
echo json_encode($arr);

保存并执行以上代码的结果为:

连续数组["foo","bar","baz","blong"]
非连续数组{"1":"foo","2":"bar","3":"baz","4":"blong"}
删除一个连续数组的方式产生的非连续数组{"0":"foo","2":"baz","3":"blong"}
二维数组[{"name":"chenxiaolong"},{"name":"chenxiaolong"}]

使用json_encode()转换一个二维数组时,会在最外部有一对中括号‘[]',里面包含各个由一维数组转成的json字串。如果是连续数组,也会在最外部有一对‘[]',编码后的json字串会省略索引,直接显示值。

2. json_decode

json_decode()可对JSON格式的字符串进行解码,语法如下:

function json_decode ($json, $assoc = false, $depth = 512, $options = 0) mixed

如果没有设置第二个参数或第二个参数为false就返回一个对象;如果设置第二个参数为true就返回一个数组。

<?php
$json ='{"a":1,"b":2,"c":3,"d":4,"e":6}';
//$json ='{"1":"foo","2":"bar","3":"baz","4":"blong"}';
var_dump(json_decode($json));
echo "<br/>";
var_dump(json_decode($json,true));

保存并执行以上程序的结果如下:

object(stdClass)#1 (5) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ["d"]=> int(4) ["e"]=> int(6) }
array(5) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ["d"]=> int(4) ["e"]=> int(6) }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值