>  기사  >  백엔드 개발  >  PHP가 XML을 구문 분석하는 네 가지 방법에 대한 자세한 설명

PHP가 XML을 구문 분석하는 네 가지 방법에 대한 자세한 설명

墨辰丷
墨辰丷원래의
2018-05-31 10:21:051930검색

이 글에서는 주로 php에서 xml을 파싱하는 4가지 방법에 대한 관련 정보를 자세하게 소개하고 있으니 필요한 친구들은 참고하시면 됩니다.

php에서 xml을 파싱하는 4가지 방법

XML 처리는 개발 과정에서 자주 접하게 됩니다. process 예, PHP는 이에 대한 풍부한 지원도 제공합니다. 이 기사에서는 Xml 파서, SimpleXML, XMLReader, DOMDocument를 포함한 일부 구문 분석 기술만 간략하게 설명합니다.

1. XML Expat 파서:

XML 파서는 Expat XML 파서를 사용합니다. Expat는 XML 문서를 일련의 이벤트로 처리하는 이벤트 기반 파서입니다. 이벤트가 발생하면 지정된 함수를 호출하여 이를 처리합니다. Expat는 문서에 연결된 모든 DTD를 무시하는 검증이 필요 없는 파서입니다. 그러나 문서의 형식이 좋지 않으면 오류 메시지가 표시됩니다. 이벤트 기반이고 유효성 검사가 없기 때문에 Expat는 빠르고 웹 애플리케이션에 적합합니다.

XML Parser의 장점은 XML 문서 전체를 메모리에 올려서 처리하는 것이 아니라 파싱하면서 처리하기 때문에 성능이 좋다는 것입니다. 그러나 바로 이 때문에 XML 구조를 동적으로 조정하거나 XML 컨텍스트 구조를 기반으로 복잡한 작업을 수행해야 하는 사용자에게는 적합하지 않습니다. 잘 구성된 XML 문서를 구문 분석하고 처리하려는 경우 작업을 잘 완료할 수 있습니다. XML Parser는 US-ASCII, ISO-8859-1 및 UTF-8의 세 가지 인코딩 형식만 지원합니다. XML 데이터가 다른 인코딩으로 되어 있는 경우 먼저 위 세 가지 중 하나로 변환해야 합니다.
일반적으로 XML Parser에 일반적으로 사용되는 두 가지 구문 분석 방법(실제로는 두 가지 기능)이 있습니다: xml_parse_into_struct 및 xml_set_element_handler.

xml_parse_into_struct

이 방법은 xml 데이터를 두 개의 배열로 구문 분석합니다.

index 배열 - 값 배열의 값 위치에 대한 포인터를 포함합니다.
값 배열 - 구문 분석된 XML의 데이터를 포함합니다.

이 두 배열을 텍스트로 설명하는 것은 약간 번거롭습니다. 예를 살펴보겠습니다(PHP 공식 문서).

$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);

출력:

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
    )
)

인덱스 배열에 레이블 이름 키와 해당 값은 값 배열에서 이 모든 태그의 위치를 ​​포함하는 배열입니다. 그런 다음 이 위치를 통해 이 레이블에 해당하는 값을 찾습니다.

xml의 각 데이터 집합의 형식이 다르고 완전히 통합할 수 없는 경우 코드를 작성할 때 주의해야 하며 잘못된 결과가 나올 수 있습니다. 예를 들어 다음의 예는

$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);

위의 방법으로 트래버스하면 코드는 단순해 보이지만, 가장 치명적인 것은 잘못된 결과를 얻을 위험이 숨어있습니다(extra3). 내부의 두 번째 파라로 실행됩니다). 따라서 좀 더 엄격한 방식으로 탐색해야 합니다.

$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;
}

사실 저는 xml_parse_into_struct 함수를 거의 사용하지 않으므로 위의 소위 "엄격한" 코드가 유지되지 않으면 다른 상황에서 버그가 발생할 수 있습니다. . - -|

xml_set_element_handler

파서가 요소의 시작과 끝을 처리할 수 있도록 콜백 함수를 설정하는 방법입니다. 또한 파서에 대한 데이터를 설정하는 데 사용되는 콜백 함수 xml_set_character_data_handler도 포함되어 있습니다. 이런 방식으로 작성된 코드는 더 명확하고 유지 관리가 더 쉽습니다.

예:

$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);

set 핸들러 메소드는 코드 라인이 많지만 아이디어가 명확하고 가독성이 좋지만 성능이 첫 번째 메소드보다 약간 느리고 유연성이 떨어지는 것을 볼 수 있습니다. 강한. XML Parser는 PHP4를 지원하며 이전 버전을 사용하는 시스템에 적합합니다. PHP5 환경에서는 다음 방법을 우선적으로 사용하세요.

2. SimpleXML

SimpleXML은 PHP5 이후에 제공되는 간단하고 사용하기 쉬운 xml 도구 모음입니다. xml을 처리하기 편리한 객체로 변환할 수 있고 xml 데이터를 구성하고 생성할 수도 있습니다. 단, 네임스페이스를 포함하는 xml에는 적용되지 않으며, xml은 올바른 형식이어야 합니다. simplexml_import_dom, simplexml_load_file, simplexml_load_string의 세 가지 메소드를 제공합니다. 함수 이름을 보면 직관적으로 함수를 알 수 있습니다. 세 가지 함수 모두 SimpleXMLElement 개체를 반환하며 SimpleXMLElement 작업을 통해 데이터를 읽거나 추가합니다.

$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);

SimpleXML의 장점은 개발이 간단하다는 점입니다. 단점은 처리하기 전에 XML 전체를 메모리에 로드하므로 내용이 많은 XML 문서를 구문 분석하지 못할 수도 있다는 것입니다. . 작은 파일을 읽는 중이고 xml에 네임스페이스가 없으면 SimpleXML이 좋은 선택입니다.

3. XMLReader

XMLReader는 PHP5 이후의 확장 기능입니다(5.1 이후 기본적으로 설치됨). 이는 커서처럼 문서 흐름에서 이동하며 각 노드에서 중지됩니다. 이는 입력에 대한 빠르고 캐시되지 않은 스트리밍 액세스를 제공하며, 스트림이나 문서를 읽을 수 있어 사용자가 여기에서 데이터를 추출하고 애플리케이션에 의미가 없는 레코드를 건너뛸 수 있습니다.

Google Weather API를 사용하여 정보를 얻는 예는 XMLReader의 사용을 보여줍니다. 여기에는 소수의 기능만 포함되어 있으며, 자세한 내용은 공식 문서를 참조하세요.

$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和XML Parser类似,都是边读边操作,较大的差异在于SAX模型是一个“推送”模型,其中分析器将事件推到应用程序,在每次读取新节点时通知应用程序,而使用XmlReader的应用程序可以随意从读取器提取节点,可控性更好。
由于XMLReader基于libxml,所以有些函数要参考文档看看是否适用于你的libxml版本。

4。 DOMDocument

DOMDocument还是PHP5后推出的DOM扩展的一部分,可用来建立或解析html/xml,目前只支持utf-8编码。

$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处理方式,开发人员在选择上就要花些时间了解,选择适合项目需求及系统环境、又便于维护的方法。

以上就是本文的全部内容,希望对大家的学习有所帮助。


相关推荐:

phpStudy中升级MySQL版本方法

php7安装yar扩展的方法

PHP如何实现腾讯与百度坐标转换

위 내용은 PHP가 XML을 구문 분석하는 네 가지 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.