# PHP中XML处理

* DOM ：一次性将xml载入内存，内存问题需要注意
* SimpleXML：小文件可以选择它，不支持命令空间
* XMLReader  :  边读边操作, “拉取”模型,大文件操作
* XML Parser  :  SAX模型是一个“推送”模型,大文件操作

## SimpleXML

**语法**

PHP的语法simplexml\_load\_string（）函数具有以下语法。

```php
simplexml_load_string(data,classname,options,ns,is_prefix);
```

**参数**

| 参数         | 是必须的 | 描述                                                          |
| ---------- | ---- | ----------------------------------------------------------- |
| 数据         | 需要。  | 一个格式正确的XML字符串                                               |
| 班级名称       | 可选的。 | 新对象的类                                                       |
| 选项         | 可选的。 | 额外的Libxml参数。通过指定选项和1或0（TRUE或FALSE，例如LIBXML\_NOBLANKS（1））来设置 |
| ns         | 可选的。 | 命名空间前缀或URI                                                  |
| is\_prefix | 可选的。 | 如果ns是前缀，则为TRUE。如果ns是URI，则为FALSE。默认值为FALSE                   |

**选项的可能值：**

LIBXML\_COMPACT - 激活节点分配优化（可加速应用程序）

* LIBXML\_DTDATTR - 设置默认DTD属性
* LIBXML\_DTDLOAD - 加载外部子集
* LIBXML\_DTDVALID - 使用DTD进行验证
* LIBXML\_NOBLANKS - 删除空白节点
* LIBXML\_NOCDATA - 将CDATA合并为文本节点
* LIBXML\_NOEMPTYTAG - 展开空标记（例如对\<br> \</ br>），仅在DOMDocument-> save（）和DOMDocument-> saveXML（）函数中可用
* LIBXML\_NOENT - 替代实体
* LIBXML\_NOERROR - 不显示错误报告
* LIBXML\_NONET - 加载文档时禁用网络访问
* LIBXML\_NOWARNING - 不显示警告报告
* LIBXML\_NOXMLDECL - 保存文档时删除XML声明
* LIBXML\_NSCLEAN - 删除多余的命名空间声明
* LIBXML\_PARSEHUGE - 设置XML\_PARSE\_HUGE标志，放宽解析器的任何硬编码限制。这会影响极限，如文档的最大深度和文本节点大小的限制
* LIBXML\_XINCLUDE - 实现XInclude替换
* LIBXML\_ERR\_ERROR - 获取可恢复的错误
* LIBXML\_ERR\_FATAL - 获取致命错误
* LIBXML\_ERR\_NONE - 获取无错误
* LIBXML\_ERR\_WARNING - 获取简单的警告
* LIBXML\_VERSION - 获取libxml版本
* LIBXML\_DOTTED\_VERSION - 获取点分的libxml版本

**返回值**

成功时返回SimpleXMLElement对象。失败时为FALSE。

**示例**

简单示例

```php
$string = <<<XML
<?xml version='1.0'?>
<document>
  <cmd>login</cmd>
  <login>imdonkey</login>
</document>
XML;

$xml = simplexml_load_string($string);
print_r($xml);
```

结果:

```
SimpleXMLElement Object ( [cmd] => login [login] => imdonkey )
```

文件不大时,可以配合以下方式转为数组使用

```php
$string = <<<XML
<?xml version='1.0'?>
<document>
<cmd>login</cmd>
<login>imdonkey</login>
</document>
XML;

$xml = simplexml_load_string($string);
$arr = toArray($xml);
print_r($arr);
echo $arr['cmd'];

function toArray($object)
{
    $object = json_decode(json_encode($object), true);
    return $object;
}
```

### 常见CDATA 包裹数据处理

```php
simplexml_load_string($string, null, LIBXML_NOCDATA);
```

示例:

```php
$string = <<<XML
<?xml version='1.0'?>
<document>
<cmd><![CDATA[login]]></cmd>
<login><![CDATA[imdonkey]]></login>
</document>
XML;

$xml = simplexml_load_string($string, null, LIBXML_NOCDATA);
var_dump($xml);
```

资料:

[微信开发基础之php函数simplexml\_load\_string](http://www.phpos.net/jichu/132.html)

## XMLReader

```
<?xml version="1.0" encoding="utf-8"?>
<collection>
 <cd>
  <title type="hk">港台明星</title>
  <artist>刘德华</artist>
  <year>1995</year>
 </cd>
 <cd>
  <title>大陆演员</title>
  <artist>范冰冰</artist>
  <year>1997</year>
 </cd>
</collection><?xml version="1.0" encoding="utf-8"?>
<collection>
 <cd>
  <title type="hk">港台明星</title>
  <artist>刘德华</artist>
  <year>1995</year>
 </cd>
 <cd>
  <title>大陆演员</title>
  <artist>范冰冰</artist>
  <year>1997</year>
 </cd>
</collection>
```

示例

```php
<?php
$items=array();
$reader=new XMLReader();
$reader->open('collection.xml', 'utf-8');
while ($reader->read()){
  //get current data
  if($reader->name=="cd" && $reader->nodeType==XMLReader::ELEMENT){
    $item=[];
    while($reader->read() && $reader->name !="cd" ){
        if($reader->nodeType!=XMLReader::ELEMENT)continue;
        $name=$reader->name;
        $value=$reader->readString();
        $item[$name]=$value;
    }
     $items[]=$item;
  }
}
$reader->close();

print_r($items);
```

## XML Parser

```php
<?php

$file = "collection.xml";
$depth = array();

function startElement($parser, $name, $attrs) 
{
    global $depth;
     /*
    for ($i = 0; $i < $depth[$parser]; $i++) {
        echo "  ";
    }*/
    //echo "$name\n";
    print_r($attrs);
    //$depth[$parser]++;
}

function endElement($parser, $name) 
{
    global $depth;
    //$depth[$parser]--;
}

function data($parser, $data) {
    var_dump($data);
}

$xml_parser = xml_parser_create('UTF-8');
xml_parser_set_option ( $xml_parser , XML_OPTION_SKIP_WHITE  , 1 ) ;
xml_parser_set_option ( $xml_parser , XML_OPTION_CASE_FOLDING  , 0 ) ;

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "data");

$fp = fopen($file, "r");


while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("XML error: %s at line %d",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);
```
