PHP最佳的XML解析器

152

我以前使用过XML解析器,虽然它工作得还可以,但总体上我并不满意它,感觉我在使用它时需要使用一些绕道解决的方式来实现本应该是基本功能的东西。

我最近看到了SimpleXML,但还没有试过。它更简单吗?两者有什么优缺点?你使用过其他解析器吗?


4
建议阅读此内容的任何人:提出一个问题,描述您需要对XML进行的操作(除了简单解析之外),您很可能会得到更好的答案。 - Shog9
2
请参阅以下关于 PHP 标签的通用参考问题:**如何使用 PHP 解析和处理 HTML/XML?** - hakre
6个回答

110

我必须说 SimpleXML 是最好的选择,因为它是一个用C语言编写的扩展,并且非常快。其次,解析后的文档采用了PHP对象的形式。因此,您可以像这样“查询”:$root->myElement


14
simplexml 是最好的,但与命名空间一起使用时效果并不那么好,有时可能会变得棘手。 - pleasedontbelong
2
是的,我也认为这是最好的选择。 而且我使用xpath来处理它。 $xml->xpath("//block");//这太棒了 :) - Vahan
5
我不认为这是最好的选择。它不支持xml version="1.1",并会发出警告(我的PHP版本是5.3.6)。我知道你可以禁用警告并且仍然能正常工作,但我不认为这是一个好的解决方案。所以想象一下,如果你的API提供商将xml文档版本从1.0更改为1.1,会发生什么?第二点是@Gordon指出的。SimpleXML将整个文档加载到内存中。这是一个不错的解决方案,但肯定不是最好的。 - Karol
9
使用SimpleXML处理命名空间XML很麻烦。 - Jake Wilson
4
当一个节点只有一个子节点和多个子节点时,SimpleXML创建不同的结构。这让我很不舒服! - Adam Pietrasiak
显示剩余5条评论

43

请查看PHP的可用XML扩展

XML解析器和SimpleXML之间的主要区别在于后者不是拉模式解析器。SimpleXML基于DOM扩展构建,并将整个XML文件加载到内存中。像XMLReader这样的XML解析器仅会将当前节点加载到内存中。您为特定节点定义处理程序,当解析器遇到它时就会触发这些处理程序。这样做更快,可以节省内存。但您无法使用XPath。

个人而言,我认为SimpleXml在提供与DOM相比有限的功能方面很“简单”。但是,您可以轻松地在DOM和SimpleXml之间切换,但我通常不会费心直接使用DOM。DOM是W3C DOM API的实现,因此您可能熟悉它来自其他语言的使用,例如JavaScript。


那么你主要使用什么? - Pratik Joshi
1
抱歉 - 我只是在寻找有关API差异的信息,所以来到这里。两个devzone链接都已失效,不确定是否应该删除或更新它们。 - Nigel Ren

39

当没有可用的扩展程序时,这是一种快速简便的XML解析函数:

<?php
/**
 * Convert XML to an Array
 *
 * @param string  $XML
 * @return array
 */
function XMLtoArray($XML)
{
    $xml_parser = xml_parser_create();
    xml_parse_into_struct($xml_parser, $XML, $vals);
    xml_parser_free($xml_parser);
    // wyznaczamy tablice z powtarzajacymi sie tagami na tym samym poziomie
    $_tmp='';
    foreach ($vals as $xml_elem) {
        $x_tag=$xml_elem['tag'];
        $x_level=$xml_elem['level'];
        $x_type=$xml_elem['type'];
        if ($x_level!=1 && $x_type == 'close') {
            if (isset($multi_key[$x_tag][$x_level]))
                $multi_key[$x_tag][$x_level]=1;
            else
                $multi_key[$x_tag][$x_level]=0;
        }
        if ($x_level!=1 && $x_type == 'complete') {
            if ($_tmp==$x_tag)
                $multi_key[$x_tag][$x_level]=1;
            $_tmp=$x_tag;
        }
    }
    // jedziemy po tablicy
    foreach ($vals as $xml_elem) {
        $x_tag=$xml_elem['tag'];
        $x_level=$xml_elem['level'];
        $x_type=$xml_elem['type'];
        if ($x_type == 'open')
            $level[$x_level] = $x_tag;
        $start_level = 1;
        $php_stmt = '$xml_array';
        if ($x_type=='close' && $x_level!=1)
            $multi_key[$x_tag][$x_level]++;
        while ($start_level < $x_level) {
            $php_stmt .= '[$level['.$start_level.']]';
            if (isset($multi_key[$level[$start_level]][$start_level]) && $multi_key[$level[$start_level]][$start_level])
                $php_stmt .= '['.($multi_key[$level[$start_level]][$start_level]-1).']';
            $start_level++;
        }
        $add='';
        if (isset($multi_key[$x_tag][$x_level]) && $multi_key[$x_tag][$x_level] && ($x_type=='open' || $x_type=='complete')) {
            if (!isset($multi_key2[$x_tag][$x_level]))
                $multi_key2[$x_tag][$x_level]=0;
            else
                $multi_key2[$x_tag][$x_level]++;
            $add='['.$multi_key2[$x_tag][$x_level].']';
        }
        if (isset($xml_elem['value']) && trim($xml_elem['value'])!='' && !array_key_exists('attributes', $xml_elem)) {
            if ($x_type == 'open')
                $php_stmt_main=$php_stmt.'[$x_type]'.$add.'[\'content\'] = $xml_elem[\'value\'];';
            else
                $php_stmt_main=$php_stmt.'[$x_tag]'.$add.' = $xml_elem[\'value\'];';
            eval($php_stmt_main);
        }
        if (array_key_exists('attributes', $xml_elem)) {
            if (isset($xml_elem['value'])) {
                $php_stmt_main=$php_stmt.'[$x_tag]'.$add.'[\'content\'] = $xml_elem[\'value\'];';
                eval($php_stmt_main);
            }
            foreach ($xml_elem['attributes'] as $key=>$value) {
                $php_stmt_att=$php_stmt.'[$x_tag]'.$add.'[$key] = $value;';
                eval($php_stmt_att);
            }
        }
    }
    return $xml_array;
}
?>

3
在我正在处理的几个脚本中,SimpleXML 无法正常工作,但这个方法却非常成功,谢谢。 - E Ciotti
出现错误- 注意:未定义变量:xml_array。 - Shahulktm
2
谢谢,这个简单的XML解决了我的问题! - Vilk

19

嗨,我认为SimpleXml非常有用。 而且我正在使用 xpath

$xml = simplexml_load_file("som_xml.xml");

$blocks  = $xml->xpath('//block'); //gets all <block/> tags
$blocks2 = $xml->xpath('//layout/block'); //gets all <block/> which parent are   <layout/>  tags

我使用许多xml配置,这使得我可以非常快速地解析它们。 SimpleXml是用C编写的,因此非常快速。


13

这取决于您想要对XML文件做什么。如果您只是想读取XML文件(比如配置文件),那么The Wicked Flea建议使用SimpleXML是正确的,因为它创建了类似嵌套ArrayObjects的内容结构。例如,可以通过 $xml->root->child 访问值。

如果您想要操作XML文件,最好使用DOM XML


0

12
你可能希望披露你是这个班级的作者。 - Brad Larson
PHPClasses.org 还在运营吗?编辑:哦,我猜它还在2011年。 - Phillip Harrington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接