我需要更快的方法来将XML解析为数组(没有空值)。
到目前为止,我正在使用Array2XML(由Lalit Patel开发)库将XML解析为数组,但这是脚本的瓶颈。我当时想加快速度,发现速度提高了大约15倍:
class SimpleXmlDecoder
{
public function decode(string $xml): array
{
try {
$decoded = json_decode(json_encode(
simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)
),TRUE);
if (empty($decoded)) {
return [];
}
return self::mapEmptyArraysElementsToEmptyString($decoded);
} catch (\Exception $exception) {
return [];
}
}
private static function mapEmptyArraysElementsToEmptyString($array): array
{
return array_map(
static function($value) {
if (!is_array($value)) {
return $value;
}
if (empty($value)) {
return '';
}
return self::mapEmptyArraysElementsToEmptyString($value);
},
$array
);
}
}
现在足够了,但将来可能成为瓶颈。您知道更快的方法吗?
@编辑 每个XML的大小:100kB-1MB 需要具有名称和值的所有NON-EMPTY元素的返回值。
答案 0 :(得分:0)
您可以使用simplexml_load_string()函数来解析xml。请参阅“ https://www.w3schools.com/php/php_xml_simplexml_read.asp”以了解更多信息。
答案 1 :(得分:0)
我只是快速地将下面的xmlparser
类拼凑在一起,该类使用RecursiveDOMIterator
类来处理xml文件。我不知道这是否比您的原始代码要快-在本地处理文件时看起来很活跃-它可以在2.4秒内处理非常复杂的8Mb xml文件,但可以压缩较小的文件。我很想知道它在比较中的表现
<?php
class RecursiveDOMIterator implements RecursiveIterator {
/*
https://github.com/salathe/spl-examples/wiki/RecursiveDOMIterator
*/
private $index;
private $list;
public function __construct(DOMNode $domNode){
$this->index = 0;
$this->list = $domNode->childNodes;
}
public function current(){
return $this->list->item($this->index);
}
public function getChildren(){
return new self( $this->current() );
}
public function hasChildren(){
return $this->current()->hasChildNodes();
}
public function key(){
return $this->index;
}
public function next(){
$this->index++;
}
public function rewind(){
$this->index = 0;
}
public function valid(){
return $this->index < $this->list->length;
}
}//end class
class xmlparser{
private static $instance=false;
private $start;
private $dom;
private function __construct( $xml ){
$this->start=microtime( true );
libxml_use_internal_errors( true );
$this->dom=new DOMDocument;
$this->dom->validateOnParse=true;
$this->dom->recover=true;
$this->dom->strictErrorChecking=true;
if( is_file( $xml ) && file_exists( $xml ) ) $this->dom->load( $xml );
else $this->dom->loadXML( $xml );
libxml_clear_errors();
}
private function __clone(){}
public function __wakeup(){}
public static function initialise( $xml ){
if( !self::$instance ) self::$instance=new xmlparser( $xml );
return self::$instance;
}
public function parse(){
$itr = new RecursiveIteratorIterator( new RecursiveDOMIterator( $this->dom ), RecursiveIteratorIterator::SELF_FIRST );
$tmp=[];
foreach( $itr as $node) {
if( $node->nodeType === XML_ELEMENT_NODE ) {
$tag=$node->tagName;
$value=$node->nodeValue;
if( !empty( $value ) ){
$element=[
'tag' => $tag,
'value' => $value
];
if( $node->hasAttributes() ){
$attributes=[];
foreach( $node->attributes as $index => $attr ){
$attributes[ $attr->nodeName ]=$attr->nodeValue;
}
$element['attributes']=$attributes;
}
$tmp[]=$element;
}
}
}
$this->duration=microtime( true ) - $this->start;
return $tmp;
}
public function __get( $name ){
return $this->$name;
}
}//end class
$file = 'bbc_rss.xml';
$obj = xmlparser::initialise( $file );
$data = $obj->parse();
$time = $obj->duration;
$size = round( $obj->filesize/pow( 1024, 2 ),2 );
printf( "Time: %s\nSize:%sMb", $time, $size );
?>
答案 2 :(得分:0)
您可以使用SAX parser
,使用它可以解析大文件。
SAX解析器用于解析XML文件,并且比示例XML解析器和DOM更好地用于内存管理。它不会在内存中保留任何数据,因此可以用于非常大的文件。以下示例将展示如何使用SAX API从XML获取数据。