【问题标题】:Create array out of XML data使用 XML 数据创建数组
【发布时间】:2012-08-31 23:34:42
【问题描述】:

由于 Zend_Rest_Client_Result 对象,我有一个像这样的简单 xml 对象。

<userdetails>
  <name value="jake"/>
  <type value="user"/>
  <attribute name="fname">
    <value>Jake</value>
  </attribute>
  <attribute name="lname">
    <value>Gordon</value>
  </attribute>
  <attribute name="phone">
    <value>123-555-1234</value>
    <value>999-888-7777</value> 
  </attribute>
 </userdetails>

如何使用 PHP 从上述 XML 对象创建这样的数组?

 $userDetails = array();
 $userDetails["name"] = "jake";
 $userDetails["type"] = "user";
 $userDetails["fname"] = "Jake";
 $userDetails["lname"] = "Gordon";
 $userDetails["phone"][0] = "123-555-1234";
 $userDetails["phone"][1] = "123-555-1234";

谢谢,

【问题讨论】:

    标签: php xml zend-framework dom xml-parsing


    【解决方案1】:
    $xml = '<userdetails><name value="jake"/><type value="user"/><attribute name="fname"><value>Jake</value></attribute><attribute name="lname"><value>Gordon</value></attribute><attribute name="phone"><value>123-555-1234</value><value>999-888-7777</value></attribute></userdetails>';
    
    $simple = new SimpleXMLElement($xml);
    $array = array();
    
    if(isset($simple->name))
      $array['name'] = (string) $simple->name->attributes()->value;
    
    if(isset($simple->type))
      $array['type'] = (string) $simple->type->attributes()->value;
    
    if($foreach = $simple->xpath('//attribute[@name="fname"]/value'))
    {
      foreach($foreach as $node)
      {
        $array['fname'] = (string) $node;
      }
    }
    
    if($foreach = $simple->xpath('//attribute[@name="lname"]/value'))
    {
      foreach($foreach as $node)
      {
        $array['lname'] = (string) $node;
      }
    }
    
    if($foreach = $simple->xpath('//attribute[@name="phone"]/value'))
    {
      $array['phone'] = array();
      foreach($simple->xpath('//attribute[@name="phone"]/value') as $node)
      {
        $array['phone'][] = (string) $node;
      }
    }
    
    print_r($array);
    

    【讨论】:

    • 快速问题.. 如果 fname 或 lname 或 phone 属性不存在,PHP 会发出警告,但会在 foreach 循环中使用。我怎样才能保护我的代码免受这种影响?
    • 将 xpath 搜索的结果存储到 foreach 循环之前的变量中,并针对变量不为空进行测试。请参阅我的更新答案。
    【解决方案2】:
    function xmlstr_to_array($xmlstr) {
      $doc = new DOMDocument();
      $doc->loadXML($xmlstr);
      return domnode_to_array($doc->documentElement);
    }
    
    function domnode_to_array($node) {
      $output = array();
      switch ($node->nodeType) {
       case XML_CDATA_SECTION_NODE:
       case XML_TEXT_NODE:
        $output = trim($node->textContent);
       break;
       case XML_ELEMENT_NODE:
        for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
         $child = $node->childNodes->item($i);
         $v = domnode_to_array($child);
         if(isset($child->tagName)) {
           $t = $child->tagName;
           if(!isset($output[$t])) {
            $output[$t] = array();
           }
           $output[$t][] = $v;
         }
         elseif($v) {
          $output = (string) $v;
         }
        }
        if(is_array($output)) {
         if($node->attributes->length) {
          $a = array();
          foreach($node->attributes as $attrName => $attrNode) {
           $a[$attrName] = (string) $attrNode->value;
          }
          $output['@attributes'] = $a;
         }
         foreach ($output as $t => $v) {
          if(is_array($v) && count($v)==1 && $t!='@attributes') {
           $output[$t] = $v[0];
          }
         }
        }
       break;
      }
      return $output;
    }
    ?>
    

    另一种快速而肮脏的方法是:

    <?php
      $a = json_decode(json_encode((array) simplexml_load_string($s)),1);
    ?>
    

    这不太健壮,并且会在您编写包含 CDATA 节点的代码时产生问题。

    【讨论】:

      猜你喜欢
      • 2021-10-02
      • 2014-07-24
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多