天天看点

Discuz! 安装插件和风格出现错误提示"数据类型错误,请返回。 php xml 正确的解析方式

1- 环境

  WindowsXp

  PHP5.2.5

  Apache 2.0.55

2- 解析XML

  2-1 什么是DOM

  DOM(Document Object Model),是根据W3C的DOM规范建立的一种与浏览器,平台,语言无关的接口,使其可以访问页面其他的标准组件。它是以层次结构组织的节点或信息片断的集合。(如:XML文件),解析后以树形节点方式存在,DOM允许开发人员添加,编辑,移动或删除树中任意位置的节点。

  当前DOM分为三个阶段分别是:Level1,Level2,Level3。

  Level1:包括对 XML 1.0 和 HTML 的支持,每个 HTML 元素被表示为一个接口。它包括用于添加、编辑、移动和读取节点中包含的信息的方法,等等。然而,它没有包括对 XML 名称空间(XML Namespace)的支持,XML 名称空间提供分割文档中的信息的能力。

  Level2:添加了名称空间支持。Level 2 扩展了 Level 1,允许开发人员检测和使用可能适用于某个节点的名称空间信息。Level2 还增加了几个新的模块,以支持级联样式表、事件和增强的树操作。

  Level3: 包括对创建 Document 对象(以前的版本将这个任务留给实现,使得创建通用应用程序很困难)的更好支持、增强的名称空间支持,以及用来处理文档加载和保存、验证以及 XPath 的新模块;XPath 是在 XSL 转换(XSL Transformation)以及其他 XML 技术中用来选择节点的手段。

  *DOM不只是XML,而XML必然是DOM。

  2-2 什么是DTD

  DTD(Documnet Type Definition),DTD 是一套关于标记符的语法规则。它是XML1.0版规格得一部分,是XML文件的验证机制,属于XML文件组成的一部分。

  DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。一个DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。

  XML文件提供应用程序一个数据交换的格式,DTD正是让XML文件能够成为数据交换的标准,因为不同的公司只需定义好标准的DTD,各公司都能够依照 DTD建立XML文件,并且进行验证,如此就可以轻易的建立标准和交换数据,这样满足了网络共享和数据交互。DTD文件是一个ASCII的文本文件,后缀名为.dtd。

  2-3 什么是XPath

  XPath 是一种在XML文档中查找信息的语言。XPath用于在XML文档中通过元素和属性进行导航。

  XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

3- 当前PHP中解析XML文件的四种方式

(1)SAX方式(Simple API for XML),简单XML解析API,以函数形式存在;(可封装但不能被继承)

(2)纯DOM方式,当前PHP5支持到DOM Level2,以类方式存在;(可继承与封装)

(3)DOMXML方式,基于DOM方式PHP将其封装后以函数形式(可封装但不能被继承)--笔者推荐方式

(4)SimpleXML方式,PHP独有XML解析API,被直接绑定在PHP5中并被应用,可直接对DOM对象进行直接XML操作,以函数形式存在(可封装但不能被继承)

  3-1 SAX方式解析XML文档

  从PHP3起就被装入,基于W3C开发的一种用于解析XML文件方式。在该种方式下使用PHP的以xml_XXXX系列函数组成,在该种方式下是以建立各要素的Handler(句柄),后按照文件读入方式进行解析的一种方式,被直接编译到PHP中,不需加载PECL,以函数返回句柄方式处理,因为采用字节读取方式因此不能建立XmlTree,因此不使用XPath对XML进行快速方便的解析。

  但对<!DOCTYPE中的ENTITY(实体)不能进行很好的解析。(在PHP5中不能解析,PHP4解析正常)如:

<?xml version="1.0" encoding="utf-8" ?> 

<!DOCTYPE value SYSTEM "../../_common/value.dtd" [

<!ENTITY list1 '

        <val type="num">0.0</val>        <valtype="num">3.0</val>        <val type="num">4.0</val>        <val type="num">5.0</val>        <valtype="num">6.0</val>        <valtype="num">8.0</val>'>]><paramname='list1'>&list1</param>

另外,该种解析方式当前已被PHP中的另三种方式所取代。

简单代码示例:

<?php

// 建立节点开始Tag解析函数(得到解析Handle指定后)function starting_handler($parser, $elementname, $attributes) {

   print "Starting handler for $elementname <BR />";

}

// 建立节点结束Tag解析函数(得到解析句柄后)[size=+0]function ending_handler($parser, $elementname) {

      print "Ending handler for $elementname <BR />";

}

$xmlfile = 'myxmlfile.xml';

// 创建parser对象

$xmlparser = xml_parser_create();

// 建立解析对Tag所指向的函数名称Handle指定

xml_set_element_handler($xmlparser, "starting_handler", "ending_handler");

// 打开XML文件并按字节读取解析$fp = fopen($xmlfile,'r');

while ($xmldata = fread($fp,1024)) {

      // 解析字节数据并将其进行解析      if (!xml_parse($xmlparser, $xmldata, feof($fp))) {

            // 如果解析遇到问题则显示错误信息及错误行列信息情况。            die( print "ERROR: "

              . xml_error_string(xml_get_error_code($xmlparser))

              . "<BR />"

              . "Line: "

              . xml_get_current_line_number($xmlparser)

              . "<BR />"

              . "Column: "

              . xml_get_current_column_number($xmlparser)

              . "<BR />");

       }

}

// 释放解析对象,结构解析xml_parser_free($xmlparser);

?>

  3-2 纯DOM解析方式解析XML文档

  从PHP5开始被引入的一组纯DOM类,以DOMXXXX类形式存在,该种方式是使用new关键字创建类对象,对类对象进行操作的一种方式,在该种方式下,由于是以类方式存在,因此在PHP5下可以建立扩展(继承,extends)关系按照个人喜好进行编码。该种方式可以很好的解析XML中 ENTITY(实体),并对XML文件的有效性进行验证。(DTD,Document Type Definition,XML1.0规格部件,用于验证XML文档的编写有效性。)

  但在该种方式下打开PHP5的“zend.ze1_compatibility_mode” (PHP4,5互兼容,使用PHP4的对象方式处理对象)设置为“On”时会出错。

  错误情况:由于该类在PHP5下被开发,但PHP4下没有,因此当设置“zend.ze1_compatibility_mode”后,PHP所有所使用new(包括继承)时都会出错,出现致命运行错误,导致文件不能被解析。如:$xpath = new DOMXpath的这种方式。

  原因:可能是BUG。(个人论断)

  纵观PHP5的所有升级LOG中在较大版本中都会出现“zend.ze1_compatibility_mode”调整的FIX被追加到所有PHP大的版本升级中,如:5.2,5.1,5.0中都有该设置的BUG出现与调整。可以看出该项设置就是在为PHP4打补丁,也可以看出类的“&”被柄弃采用java的clone失败(个人感觉这是PHP5的一次失败,因为在PHP4中只能使用“&”作为地址引用,虽然在PHP帮助文档中强调 clone被引用的好处及编码习惯,但我仍感觉当前PHP5下的Clone还是太弱,针对该项设置的 “zend.ze1_compatibility_mode”仍有很多问题)

  该种方式下可以与Xpath类相结合对文档结构进行快速查询。(但现PHP5下该XPath功能不是十分强大),不能使用较复杂的Xpath查询,当前 DOM方式下不能对“/book/chapter[@name='en']/para”这种方式进行解析(解析出错)。

  纯DOM方式只能处理“/book/chapter[@name='en']” 对于之后存在的节点无法解析。

简单代码示例:

<?php

// 建立DOMDocument对象,并规定解析方式(XML1.0,UTF-8编码)$dom = new DOMDocument("1.0","UTF-8");

// 载入需解析的xml文件

$dom->Load('book.xml');

// 建立Xpath对象并对指定DOM对象进行解析准备

$xpath = new DOMXPath($dom);

// 根据要求建立XPath所需解析文字$query = '//book/chapter/para/informaltable/tgroup/tbody/row/entry[@name= "en"]';//使用Xpath对象的query()或evaluate()对解析文字进行解析,并获得解析结果

$entries = $xpath->query($query);

foreach ($entries as $entry) {

   echo "Found {$entry-> nodeValue}" .

}

?>

  3-3 DOMXML方式解析XML文档

  DOMXML方式从PHP4.3.0被绑定到PHP中,基于DOM API,将DOM对象封装后以专门处理XML解析的一种DOM API函数,将有关处理XML解析方面的DOM方法,类变量进行封装或重新优化定义。

  *该种方式从PHP5开始不被绑定到PHP,而被移到PECL库中,使用时需要加载PECL扩展库---php_domxml.dll。

  由于基于DOM API,因此具有DOM相关特性,但由是属于封装接口函数,因此不具有扩展性(继承,extends)。

  该种方式是PHP专门用来解析XML文件开发,因此对于XML解析的功能十分强大,能够满足几乎所有XML文档的操作,并且支持复杂的XPath查询。

  由于是采用函数接口封装形状且自PHP4时代起就被绑定,因此不受之前所说的“zend.ze1_compatibility_mode” 设置影响,适合PHP4时代建立的大规模程序类处理对XML解析使用。(因为不受“zend.ze1_compatibility_mode” 的影响因此可以正常被“zend.ze1_compatibility_mode”机制处理,不会产生运行错误。而之前的DOM方式时会产生运行错误无法解析。)

  XPath机制被优化并可以处理复杂的查询如:“/book/chapter[@name='en']/para[@value='tv']/value”复杂的Xpath。

简单代码示例:

<?php// 根据要求建立XPath所需解析文字

$xpathstr = "/infomation/part[@name='PHP']/book";

// 打开需解析的xml文件$dom = domxml_open_file($xmlfile);// 对指定dom建立xpath解析对象并$xpath = xpath_new_context($dom);

// 对解析文字按照Xpath进行解析,并获得解析结果$books =xpath_eval($xpath, $xpathstr);

foreach ($books as $book){

        // 判断获得的节点若为Element类型且Tagname为“book”则输出结果        if($book->type == XML_ELEMENT_NODE and $book->tagname() == "book"){

                echo "BookList".$book->get_attribute("type")."BookName".$book->get_content();

        }

}

?>

  3-4 SimpleXML方式解析XML

  SimpleXml(Simple API for XML),从PHP5.0.0Beta1开始被编译进PHP中,在PHP5升级过程中不断被优化与修正。以非常直观的方式对从XML中取出的数据进行重新组合,XML的各个节点以类变量的形式可以进行方便直观的应用。

  但是只能处理简单XML文档进行解析处理,对复杂XML解析不是很适用,不能对节点进行增,删,改,移操作。

  操作开发十分简单,至5.2.5中SimpleXML函数仅有1个类,3个函数。可以像操作类对象一样操作各个节点。该方式下,可以允许将纯DOM对象进行加载并进行处理。

  该方式下可直接引用原纯dom对象,并对该对象进行SimpleXml操作。

  该种方式个人认为是补足纯DOM方式的不直观性与方便性所建立的,但是结果并不是令人很满意,虽然引入DOM但是却不能像DOM那样对XML文档中所有元素进行解析,尤其是Entity(实体,“SAX方式解析XML文档”中所说的部分),对于Xpath也不能像DomXml那样可以得理复杂查询。

  另外由于该方式也是从PHP5开始被引入,因此当设置了“zend.ze1_compatibility_mode”机制后,会像纯 DOM方式一样不能被建立,报运行时致命错误,不能正常解析。

简单代码示例:

<?php

// 建立XML文字列 $string = <<<XML<a> <b>  <c>text</c>  <c>stuff</c> </b> <d>  <c>code</c> </d></a>XML;`// 输入XML文字列并进行解析$xml = simplexml_load_string($string);// 按照Xpath方式解析,并查找结构为<a><b><c>的节点信息$result = $xml->xpath('/a/b/c');

// 对获得的节点信息进行输出while(list( , $node) =each($result)) {

   echo '/a/b/c: ',$node,"\n";

}

// 再次进行解析,查找结构为<b><c>的节点信息$result = $xml->xpath('b/c');

while(list( , $node) = each($result)) {

   echo 'b/c: ',$node,"\n";

}

?>

4- 总结

  根据以上说明我将这几种方式进行了如下总结:

  4-1 SAX方式解析XML文档优缺点  优点:

    (1)功能较健全,能满足一般XML相关文档解析工作; (含有对象封装函数)

    (2)解析最快,适合较大XML文件解析时使用;

    (3)PHP各版本间兼容性好,在不解析Entity(实体)的前提下可直接兼容;(PHP4,5,6?)

    (4)由于采用函数接口方式,因此可被封装。

    (5)可使用如ZendStudio调试并查看解析内容(变量内容可被直接查看输出);

    (6)不需加载PECL,直接编译进PHP。

  缺点:

    (1)由于解析方式采用字节方式,因此属一次手动解析过程,不能建立XmlTree,不能使用Xpath做快速解析工作。

    (2)不能对文档中各个节点进行操作(增,删,改,移);

    (3)没有提供生成XML文件机制(函数)(即,String2Xml);

    (4)编码相对复杂不直观,逻辑性强;

    (5)升级到PHP5后,对Entity(实体)不能进行解析。

  4-2 纯DOM方式解析XML文档优缺点    优点:    (1)功能健全,能满足复杂XML相关文档解析工作;(在PHP5环境下,可被继承并灵活调整)

    (2)采用类方式,编码较直观(有较强的OOP概念),编码灵活;

    (3)可对文档中各个节点进行操作(增,删,改,移);

    (4)提供可生成XML文件的机制(SaveXml);

    (5)可使用简单Xpath方式对XML进行快速检索;

    (6)可使用DTD对XML文档有效性进行验证;

    (7)不需加载PECL,直接编译进PHP5中;

    (8)可很好的解析Entity(实体)。  缺点:    (1)由于属纯DOM解析方式,因此速度与其他XML专门处理方式比较相对较慢;

    (2)PHP5专有类,不具有PHP4兼容性且不断在FIX阶段;

    (3)由于采用PHP内部类方式返回,因此不能使用如ZendStudio查看解析内容情况,不方便调试;

    (4)设置“zend.ze1_compatibility_mode” 为“On”时报致命运行错误,不能解析。

  4-3 DOMXML方式解析XML文档优缺点  优点:    (1)功能很健全,能满足复杂XML相关文档解析工作;

    (2)编码直观,处理灵活;

    (3)可对XML文档中各个节点进行操作(增,删,改,移);

    (4)提供生成XML文件的函数机制;

    (5)可使用复杂的Xpath方式对XML进行全面快速的检索,支持多级属性的Xpath组合查询;

    (6)可使用DTD对XML文档有效性进行验证;

    (7)兼容性好可灵活应用于(PHP4,5),从PHP5的LOG相关数据可以看到对于DOMXML的调整并不多,因此有理由相信,该方式的成熟稳定性。(对PHP来说稳定很重要);

    (8)由于采用函数接口方式且PHP4即被使用因此不受“zend.ze1_compatibility_mode” 设置影响;

    (9)可使用ZendStudio等工具对获得到的所有对象中内容进行查看,(必要信息),有利于开发调试;

    (10)可很好的解析Entity(实体)。  缺点:    (1)采用函数接口方式处理,影响一定扩展性;

    (2)需加载PECL并进行配置;

    (3)纯PHP思想处理方式(OOP概念不强,PHP自3以来至今思想影响较大)

    (4)容易与DOM概念混淆,DOM不只是XML,而XML必然是DOM。

    *本人推荐方式

  4-4 SimpleXML方式解析XML文档优缺点  优点:    (1)不需加载PECL扩展直接使用;

    (2)与其他三种方式相比,操作十分简单直观,节点以类对象方式存在,上手度较好;

    (3)可以进行简单Xpath查询;

    (4)可以将DOM对象引入,并以SimpleXml方式操作查询节点信息;(虽然还不是很完善)

    (5)可使用ZendStudio等工具对获得到的对象内容进行查看,有利于开发调整;

  缺点:    (1)不能像 DOM与DomXml那样对Entity(实体)进行解析;

    (2)设置“zend.ze1_compatibility_mode” 为“On”时报致命运行错误,不能解析。

    (3)PHP5专有方法,不具有PHP4兼容性且不断在FIX阶段,成熟度不高;

    经过对以上四种解析XML方式的说明,可以知道每种方式的优缺点,根据不同的要求及XML文档结构选择正确的解析方式。