{"id":506,"date":"2012-03-24T02:11:39","date_gmt":"2012-03-24T02:11:39","guid":{"rendered":"http:\/\/hgtas.com\/?p=506"},"modified":"2012-03-24T02:12:46","modified_gmt":"2012-03-24T02:12:46","slug":"xml-parsing-class-php-version","status":"publish","type":"post","link":"https:\/\/508.me\/?p=506","title":{"rendered":"XML\u5206\u6790\u7c7bphp\u7248"},"content":{"rendered":"<pre class=\"brush: php; gutter: true\">&lt;?php \r\n\r\nclass XML{ \r\n\r\n  var $parser;  #a reference to the XML parser \r\n\r\n  var $document; #the entire XML structure built up so far \r\n\r\n  var $parent;  #a pointer to the current parent - the parent will be an array \r\n\r\n  var $stack;  #a stack of the most recent parent at each nesting level \r\n\r\n  var $last_opened_tag; #keeps track of the last tag opened. \r\n\r\n  function XML(){ \r\n\r\n    $this-&gt;parser = xml_parser_create('utf-8'); \r\n\r\n    xml_parser_set_option($this-&gt;parser, XML_OPTION_CASE_FOLDING, false); \r\n\r\n    xml_set_object($this-&gt;parser, $this); \r\n\r\n    xml_set_element_handler($this-&gt;parser, 'open','close'); \r\n\r\n    xml_set_character_data_handler($this-&gt;parser, 'data'); \r\n\r\n  } \r\n\r\n  function destruct(){ xml_parser_free($this-&gt;parser); } \r\n\r\n  function  parse(&amp;$data){ \r\n\r\n    $this-&gt;document = array(); \r\n\r\n    $this-&gt;stack  = array(); \r\n\r\n    $this-&gt;parent  = &amp;$this-&gt;document; \r\n\r\n    return xml_parse($this-&gt;parser, $data, true) ? $this-&gt;document : NULL; \r\n\r\n  } \r\n\r\n  function open(&amp;$parser, $tag, $attributes){ \r\n\r\n    $this-&gt;data = ''; #stores temporary cdata \r\n\r\n    $this-&gt;last_opened_tag = $tag; \r\n\r\n    if(is_array($this-&gt;parent) and array_key_exists($tag,$this-&gt;parent)){ #if you've seen this tag before \r\n\r\n      if(is_array($this-&gt;parent[$tag]) and array_key_exists(0,$this-&gt;parent[$tag])){ #if the keys are numeric \r\n\r\n        #this is the third or later instance of $tag we've come across \r\n\r\n        $key = count_numeric_items($this-&gt;parent[$tag]); \r\n\r\n      }else{ \r\n\r\n        #this is the second instance of $tag that we've seen. shift around \r\n\r\n        if(array_key_exists(\"$tag attr\",$this-&gt;parent)){ \r\n\r\n          $arr = array('0 attr'=&gt;&amp;$this-&gt;parent[\"$tag attr\"], &amp;$this-&gt;parent[$tag]); \r\n\r\n          unset($this-&gt;parent[\"$tag attr\"]); \r\n\r\n        }else{ \r\n\r\n          $arr = array(&amp;$this-&gt;parent[$tag]); \r\n\r\n        } \r\n\r\n        $this-&gt;parent[$tag] = &amp;$arr; \r\n\r\n        $key = 1; \r\n\r\n      } \r\n\r\n      $this-&gt;parent = &amp;$this-&gt;parent[$tag]; \r\n\r\n    }else{ \r\n\r\n      $key = $tag; \r\n\r\n    } \r\n\r\n    if($attributes) $this-&gt;parent[\"$key attr\"] = $attributes; \r\n\r\n    $this-&gt;parent = &amp;$this-&gt;parent[$key]; \r\n\r\n    $this-&gt;stack[] = &amp;$this-&gt;parent; \r\n\r\n  } \r\n\r\n  function data(&amp;$parser, $data){ \r\n\r\n    if($this-&gt;last_opened_tag != NULL) #you don't need to store whitespace in between tags \r\n\r\n      $this-&gt;data .= $data; \r\n\r\n  } \r\n\r\n  function close(&amp;$parser, $tag){ \r\n\r\n    if($this-&gt;last_opened_tag == $tag){ \r\n\r\n      $this-&gt;parent = $this-&gt;data; \r\n\r\n      $this-&gt;last_opened_tag = NULL; \r\n\r\n    } \r\n\r\n    array_pop($this-&gt;stack); \r\n\r\n    if($this-&gt;stack) $this-&gt;parent = &amp;$this-&gt;stack[count($this-&gt;stack)-1]; \r\n\r\n  } \r\n\r\n} \r\n\r\nfunction count_numeric_items(&amp;$array){ \r\n\r\n  return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0; \r\n\r\n} \r\n\r\nfunction xml_unserialize($xml){\r\n\r\n  $xml_parser = new XML(); \r\n\r\n  $data = $xml_parser-&gt;parse($xml); \r\n\r\n  $xml_parser-&gt;destruct(); \r\n\r\n  return $data; \r\n\r\n} \r\n\r\n?&gt;<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>&lt;?php class XML{ var $parser; #a reference to the XM [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[],"_links":{"self":[{"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/posts\/506"}],"collection":[{"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/508.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=506"}],"version-history":[{"count":3,"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/posts\/506\/revisions"}],"predecessor-version":[{"id":508,"href":"https:\/\/508.me\/index.php?rest_route=\/wp\/v2\/posts\/506\/revisions\/508"}],"wp:attachment":[{"href":"https:\/\/508.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=506"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/508.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=506"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/508.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}