Home >php教程 >PHP开发 >Detailed introduction to the four methods of php parsing xml

Detailed introduction to the four methods of php parsing xml

高洛峰
高洛峰Original
2017-01-06 15:16:381224browse

php Four methods of parsing xml

XML processing is often encountered during the development process, and PHP also has rich support for it. This article only briefly outlines some of the parsing technologies. Description, including: Xml parser, SimpleXML, XMLReader, DOMDocument.

1. XML Expat Parser:

XML Parser uses the Expat XML parser. Expat is an event-based parser that treats XML documents as a series of events. When an event occurs, it calls a specified function to handle it. Expat is a validation-free parser that ignores any DTD linked to the document. However, if the document is not in good form, it will end up with an error message. Because it is event-based and has no validation, Expat is fast and suitable for web applications.

The advantage of XML Parser is its good performance, because it does not load the entire xml document into memory and then process it, but processes it while parsing it. But precisely because of this, it is not suitable for those who need to dynamically adjust the XML structure or perform complex operations based on the XML context structure. If you just want to parse and process a well-structured xml document, then it can complete the task well. It should be noted that XML Parser only supports three encoding formats: US-ASCII, ISO-8859-1 and UTF-8. If your xml data is in other encodings, you need to convert it to one of the above three first.
XML Parser generally has two commonly used parsing methods (actually two functions): xml_parse_into_struct and xml_set_element_handler.

xml_parse_into_struct

This method parses the xml data into two arrays:

index array - contains a pointer to the location of the value in the Value array
value array - contains data from the parsed XML

These two arrays are a bit troublesome to describe textually, so let’s look at an example (from php official documentation)

$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);

Output:

Index array
Array
(
  [PARA] => Array
    (
      [0] => 0
      [1] => 2
    )
 
  [NOTE] => Array
    (
      [0] => 1
    )
)
 
Vals array
Array
(
  [0] => Array
    (
      [tag] => PARA
      [type] => open
      [level] => 1
    )
 
  [1] => Array
    (
      [tag] => NOTE
      [type] => complete
      [level] => 2
      [value] => simple note
    )
 
  [2] => Array
    (
      [tag] => PARA
      [type] => close
      [level] => 1
    )
)

The index array uses the label name as key, and the corresponding value is an array, which includes the position of all this label in the value array. Then through this position, find the value corresponding to this label.

If the format of each set of data in xml is different and cannot be completely unified, then you should pay attention when writing code, you may get wrong results. For example, the following example:

$xml = &#39;
<infos>
<para><note>note1</note><extra>extra1</extra></para>
<para><note>note2</note></para>
<para><note>note3</note><extra>extra3</extra></para>
</infos>
&#39;;
 
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $values, $tags);
xml_parser_free($p);
$result = array();
//下面的遍历方式有bug隐患
for ($i=0; $i<3; $i++) {
 $result[$i] = array();
 $result[$i]["note"] = $values[$tags["NOTE"][$i]]["value"];
 $result[$i]["extra"] = $values[$tags["EXTRA"][$i]]["value"];
}
print_r($result);

If you traverse in the above way, the code seems simple, but there are hidden dangers. The most fatal thing is that you get the wrong result (extra3 runs into the second para). So we need to traverse in a more rigorous way:

$result = array();
$paraTagIndexes = $tags[&#39;PARA&#39;];
$paraCount = count($paraTagIndexes);
for($i = 0; $i < $paraCount; $i += 2) {
 $para = array();
 //遍历para标签对之间的所有值
 for($j = $paraTagIndexes[$i]; $j < $paraTagIndexes[$i+1]; $j++) {
  $value = $values[$j][&#39;value&#39;];
  if(empty($value)) continue;
 
  $tagname = strtolower($values[$j][&#39;tag&#39;]);
  if(in_array($tagname, array(&#39;note&#39;,&#39;extra&#39;))) {
   $para[$tagname] = $value;
  }
 }
 $result[] = $para;
}

In fact, I rarely use the xml_parse_into_struct function, so if the so-called "rigorous" code above is not preserved, there will be bugs in other situations. - -|

xml_set_element_handler

This method is to set the callback function for parser to handle the start and end of elements. Also included is the callback function xml_set_character_data_handler used to set data for the parser. The code written in this way is clearer and easier to maintain.

Example:

$xml = <<<XML
<infos>
<para><note>note1</note><extra>extra1</extra></para>
<para><note>note2</note></para>
<para><note>note3</note><extra>extra3</extra></para>
</infos>
XML;
 
$result = array();
$index = -1;
$currData;
 
function charactor($parser, $data) {
 global $currData;
 $currData = $data;
}
 
function startElement($parser, $name, $attribs) {
 global $result, $index;
 $name = strtolower($name);
 if($name == &#39;para&#39;) {
  $index++;
  $result[$index] = array();
 }
}
 
function endElement($parser, $name) {
 global $result, $index, $currData;
 $name = strtolower($name);
 if($name == &#39;note&#39; || $name == &#39;extra&#39;) {
  $result[$index][$name] = $currData;
 }
}
 
$xml_parser = xml_parser_create();
xml_set_character_data_handler($xml_parser, "charactor");
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!xml_parse($xml_parser, $xml)) {
 echo "Error when parse xml: ";
 echo xml_error_string(xml_get_error_code($xml_parser));
}
xml_parser_free($xml_parser);
 
print_r($result);

It can be seen that although the set handler method has many lines of code, it has clear ideas and better readability, but its performance is slightly slower than the first method and its flexibility Not strong. XML Parser supports PHP4 and is suitable for systems using older versions. For PHP5 environment, give priority to the following method.

2. SimpleXML

SimpleXML is a set of simple and easy-to-use XML tools provided after PHP5. It can convert XML into objects that are convenient for processing, and can also organize and generate XML data. However, it does not apply to xml containing namespace, and the xml must be well-formed. It provides three methods: simplexml_import_dom, simplexml_load_file, simplexml_load_string. The function name intuitively explains the function. All three functions return SimpleXMLElement objects, and data is read/added through SimpleXMLElement operations.

$string = <<<XML
<?xml version=&#39;1.0&#39;?>
<document>
 <cmd>login</cmd>
 <login>imdonkey</login>
</document>
XML;
 
$xml = simplexml_load_string($string);
print_r($xml);
$login = $xml->login;//这里返回的依然是个SimpleXMLElement对象
print_r($login);
$login = (string) $xml->login;//在做数据比较时,注意要先强制转换
print_r($login);

The advantage of SimpleXML is that it is simple to develop. The disadvantage is that it loads the entire xml into the memory before processing, so it may not be able to parse an xml document with a lot of content. If you are reading small files and the xml does not contain namespace, then SimpleXML is a good choice.

3. XMLReader

XMLReader is also an extension after PHP5 (installed by default after 5.1). It moves in the document flow like a cursor and stops at each node. It is very flexible to operate. It provides fast and non-cached streaming access to input, and can read a stream or document, allowing the user to extract data from it, and skip records that are not meaningful to the application.

Let’s take an example of using the Google Weather API to obtain information to demonstrate the use of XMLReader. Only a small part of the functions are involved here. For more information, please refer to the official documentation.

$xml_uri = &#39;http://www.google.com/ig/api?weather=Beijing&hl=zh-cn&#39;;
$current = array();
$forecast = array();
 
$reader = new XMLReader();
$reader->open($xml_uri, &#39;gbk&#39;);
while ($reader->read()) {
 //get current data
 if ($reader->name == "current_conditions" && $reader->nodeType == XMLReader::ELEMENT) {
  while($reader->read() && $reader->name != "current_conditions") {
   $name = $reader->name;
   $value = $reader->getAttribute(&#39;data&#39;);
   $current[$name] = $value;
  }
 }
 
 //get forecast data
 if ($reader->name == "forecast_conditions" && $reader->nodeType == XMLReader::ELEMENT) {
  $sub_forecast = array();
  while($reader->read() && $reader->name != "forecast_conditions") {
   $name = $reader->name;
   $value = $reader->getAttribute(&#39;data&#39;);
   $sub_forecast[$name] = $value;
  }
  $forecast[] = $sub_forecast;
 }
}
$reader->close();

XMLReader is similar to XML Parser. They both operate while reading. The big difference is that the SAX model is a "push" model, in which the analyzer pushes events to the application and reads new data each time. The application is notified when the node is reached, and the application using XmlReader can extract nodes from the reader at will, with better controllability.
Since XMLReader is based on libxml, you should refer to the documentation for some functions to see if they are applicable to your libxml version.

4. DOMDocument

DOMDocument is also part of the DOM extension launched after PHP5. It can be used to create or parse html/xml. Currently, it only supports utf-8 encoding.

$xmlstring = <<<XML
<?xml version=&#39;1.0&#39;?>
<document>
 <cmd attr=&#39;default&#39;>login</cmd>
 <login>imdonkey</login>
</document>
XML;
 
$dom = new DOMDocument();
$dom->loadXML($xmlstring);
print_r(getArray($dom->documentElement));
 
function getArray($node) {
 $array = false;
 
 if ($node->hasAttributes()) {
  foreach ($node->attributes as $attr) {
   $array[$attr->nodeName] = $attr->nodeValue;
  }
 }
 
 if ($node->hasChildNodes()) {
  if ($node->childNodes->length == 1) {
   $array[$node->firstChild->nodeName] = getArray($node->firstChild);
  } else {
   foreach ($node->childNodes as $childNode) {
   if ($childNode->nodeType != XML_TEXT_NODE) {
    $array[$childNode->nodeName][] = getArray($childNode);
   }
  }
 }
 } else {
  return $node->nodeValue;
 }
 return $array;
}

从函数名上看感觉跟JavaScript很像,应该是借鉴了一些吧。DOMDocument也是一次性将xml载入内存,所以内存问题同样需要注意。PHP提供了这么多的xml处理方式,开发人员在选择上就要花些时间了解,选择适合项目需求及系统环境、又便于维护的方法。

感谢阅读,希望能帮助到大家,谢谢大家对本站支持!

更多php 解析xml 的四种方法详细介绍相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn