【问题标题】:PHP - how to get specific value of curl responsePHP - 如何获取 curl 响应的特定值
【发布时间】:2016-02-03 08:17:39
【问题描述】:

我正在使用 curl 方法从 API 获取响应。它确实返回了一个 xml 响应。

响应返回一组字符串,我无法获得我想要的确切值。

这些是我的代码:

$url = 'someurlwithGETparameter';

$ch = curl_init();

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);

curl_close($ch);

例如:

< foods >
     < chinese > Shark Fin </ chinese>
     < japanese > Sushi </ japanese>
< /foods >

我想获取中餐“鱼翅”并将其放入变量中。

$chineseFood = $somethinglike['chinese'];

所以当我回显 $chineseFood 时,我会得到“鱼翅”。

请帮忙。今天刚开始CURL,对CURL不是很熟悉

非常感谢 =)

【问题讨论】:

  • 如果返回结果是 XML,您可以使用一些 PHP xml 解析器将其解析为 SimpleXML
  • 是的,我相信这就是我需要的东西。 =D
  • 将备受争议的鱼翅作为一种食物。鲨鱼作为一种美食被猎杀至灭绝。 :( -1

标签: php xml curl xml-parsing


【解决方案1】:

在 DOM 中,您可以使用 Xpath 获取特定的值和节点:

$xml = <<<'XML'
<foods>
     <chinese foodtype='soup'>Shark Fin</chinese>
     <japanese foodtype='fish'>Sushi</japanese>
     <italian foodtype='wheat'>Pasta</italian>
     <british foodtype='delicious'>fish n chips</british>
</foods>
XML;

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

var_dump(
  // the text content of an element node
  $xpath->evaluate('string(/foods/chinese)'),
  // the value of an attribute node
  $xpath->evaluate('string(/foods/chinese/@foodtype)')
);

输出:

string(9) "Shark Fin"
string(4) "soup"

如果结果未转换为标量(字符串、数字、布尔值),它将始终是一个节点列表,您可以使用 foreach 进行迭代:

foreach ($xpath->evaluate('/foods/*[@foodtype = "fish"]') as $food) {
  var_dump(
    [
      'name' => $food->textContent,
      'group' => $food->localName,
      'type' => $food->getAttribute('foodtype')
    ]
  );
}

输出:

array(3) {
  ["name"]=>
  string(5) "Sushi"
  ["group"]=>
  string(8) "japanese"
  ["type"]=>
  string(4) "fish"
}

返回的对象是 DOMNode 实例,实际类取决于节点类型。

【讨论】:

    【解决方案2】:

    从未使用过SimpleXML 我无法评论如何使用或它的易用性,但正如@hoppa 所说,您可以使用围绕DOMDocument 构建的内置Dom Parsing 函数

    $food=array();
    $data="
    <foods>
         <chinese foodtype='soup'>Shark Fin</chinese>
         <japanese foodtype='fish'>Sushi</japanese>
         <italian foodtype='wheat'>Pasta</italian>
         <british foodtype='delicious'>fish n chips</british>
    </foods>";
    
    /* Try to prevent errors from being displayed */
    libxml_use_internal_errors( true );
    
    /* Create the reference to the DOMDocument and set some properties */
    $dom=new DOMDocument;
    $dom->validateOnParse=false;
    $dom->standalone=true;
    $dom->preserveWhiteSpace=true;
    $dom->strictErrorChecking=false;
    $dom->substituteEntities=false;
    $dom->recover=true;
    $dom->formatOutput=false;
    /* Load the XML data */
    $dom->loadXML( $data );
    $parse_errs=serialize( libxml_get_last_error() );
    
    libxml_clear_errors();
    
    /* Get the root node and then iterate through it's children */
    $foods=$dom->getElementsByTagName('foods')->item(0);
    foreach( $foods->childNodes as $i => $node ) {
    
        if( $node->nodeType==XML_ELEMENT_NODE ){
            /* Elements can have attributes, use this methodology to find and get attributes */
            $foodtype=$node->hasAttribute('foodtype') ? $node->getAttribute('foodtype') : '';
            /* Do whatever you want with the tag or data etc */
            echo $node->tagName.' '.$node->nodeValue.' '.$foodtype.BR;
            /* You could store in an array for later use for example */
            $food[ $node->tagName ]=(object)array( 'type'=>$foodtype, 'value'=>$node->nodeValue );
        }
    }
    
    $dom=null;
    
    /* Later on.... */
    $type='chinese';
    echo 'From the array: '.$food[ $type ]->type.' '.$food[ $type ]->value;
    

    【讨论】:

      【解决方案3】:

      CURL 是用于执行 HTTP 请求/响应的机制。 根据上述描述,CURL 请求返​​回 XML 格式的响应。

      请尝试执行以下代码 sn-p 来解析 XML 文档。

      <?php 
      /** 
       * xml2array() will convert the given XML text to an array in the XML structure. 
       * Link: http://www.bin-co.com/php/scripts/xml2array/ 
       * Arguments : $contents - The XML text 
       *                $get_attributes - 1 or 0. If this is 1 the function will get the attributes as well as the tag values - this results in a different array structure in the return value.
       *                $priority - Can be 'tag' or 'attribute'. This will change the way the resulting array sturcture. For 'tag', the tags are given more importance.
       * Return: The parsed XML in an array form. Use print_r() to see the resulting array structure. 
       * Examples: $array =  xml2array(file_get_contents('feed.xml')); 
       *              $array =  xml2array(file_get_contents('feed.xml', 1, 'attribute')); 
       */ 
      function xml2array($contents, $get_attributes=1, $priority = 'tag') { 
          if(!$contents) return array(); 
      
          if(!function_exists('xml_parser_create')) { 
              //print "'xml_parser_create()' function not found!"; 
              return array(); 
          } 
      
          //Get the XML parser of PHP - PHP must have this module for the parser to work 
          $parser = xml_parser_create(''); 
          xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss 
          xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
          xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
          xml_parse_into_struct($parser, trim($contents), $xml_values); 
          xml_parser_free($parser); 
      
          if(!$xml_values) return;//Hmm... 
      
          //Initializations 
          $xml_array = array(); 
          $parents = array(); 
          $opened_tags = array(); 
          $arr = array(); 
      
          $current = &$xml_array; //Refference 
      
          //Go through the tags. 
          $repeated_tag_index = array();//Multiple tags with same name will be turned into an array 
          foreach($xml_values as $data) { 
              unset($attributes,$value);//Remove existing values, or there will be trouble 
      
              //This command will extract these variables into the foreach scope 
              // tag(string), type(string), level(int), attributes(array). 
              extract($data);//We could use the array by itself, but this cooler. 
      
              $result = array(); 
              $attributes_data = array(); 
      
              if(isset($value)) { 
                  if($priority == 'tag') $result = $value; 
                  else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
              } 
      
              //Set the attributes too. 
              if(isset($attributes) and $get_attributes) { 
                  foreach($attributes as $attr => $val) { 
                      if($priority == 'tag') $attributes_data[$attr] = $val; 
                      else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' 
                  } 
              } 
      
              //See tag status and do the needed. 
              if($type == "open") {//The starting of the tag '<tag>' 
                  $parent[$level-1] = &$current; 
                  if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag 
                      $current[$tag] = $result; 
                      if($attributes_data) $current[$tag. '_attr'] = $attributes_data; 
                      $repeated_tag_index[$tag.'_'.$level] = 1; 
      
                      $current = &$current[$tag]; 
      
                  } else { //There was another element with the same tag name 
      
                      if(isset($current[$tag][0])) {//If there is a 0th element it is already an array 
                          $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; 
                          $repeated_tag_index[$tag.'_'.$level]++; 
                      } else {//This sectio$data = cn will make the value an array if multiple tags with the same name appear together
                          $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
                          $repeated_tag_index[$tag.'_'.$level] = 2; 
      
                          if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                              $current[$tag]['0_attr'] = $current[$tag.'_attr']; 
                              unset($current[$tag.'_attr']); 
                          } 
      
                      } 
                      $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1; 
                      $current = &$current[$tag][$last_item_index]; 
                  } 
      
              } elseif($type == "complete") { //Tags that ends in 1 line '<tag />' 
                  //See if the key is already taken. 
                  if(!isset($current[$tag])) { //New Key 
                      $current[$tag] = $result; 
                      $repeated_tag_index[$tag.'_'.$level] = 1; 
                      if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
      
                  } else { //If taken, put all things inside a list(array) 
                      if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array... 
      
                          // ...push the new element into that array. 
                          $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; 
      
                          if($priority == 'tag' and $get_attributes and $attributes_data) { 
                              $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; 
                          } 
                          $repeated_tag_index[$tag.'_'.$level]++; 
      
                      } else { //If it is not an array... 
                          $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                          $repeated_tag_index[$tag.'_'.$level] = 1; 
                          if($priority == 'tag' and $get_attributes) { 
                              if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
      
                                  $current[$tag]['0_attr'] = $current[$tag.'_attr']; 
                                  unset($current[$tag.'_attr']); 
                              } 
      
                              if($attributes_data) { 
                                  $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; 
                              } 
                          } 
                          $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken 
                      } 
                  } 
      
              } elseif($type == 'close') { //End of tag '</tag>' 
                  $current = &$parent[$level-1]; 
              } 
          } 
      
          return($xml_array); 
      }  
          $response_array=xml2array($response);
      

      可以从响应数组变量中轻松检索来自 curl 响应的信息。

      【讨论】:

        【解决方案4】:

        这不是 curl 问题,这是解析 XML 的问题,这是您的 API 从外观上返回的内容。一个简单的解决方案是使用 PHP 提供的标准 XML 解析器之一:

        1. SimpleXML
        2. Dom Parser

        PHP 提供了更多(参见手册中的this page),但这两个就足够了。简单的 xml 解析器正是它所说的。一个简单的解析器。它适用于基本的东西,但当使用名称空间的 XML 和其他“复杂”的东西被输入它时,它就不那么理想了。 DOM 解析器基本上可以处理所有你想要的。

        在您的特定情况下, curl_exec 将返回我认为的这个 XML。如果是这种情况,您可以按照以下方式做一些事情:

        // all curl stuff here
        $xmlString = curl_exec($ch);
        $XmlElement = new SimpleXMLElement($xmlString);
        $chineseFoods = $XmlElement->chinese;
        

        您可以直接调用$XmlElement-&gt;chinese,因为食物将被解释为 XML“文档”的根节点

        【讨论】:

        • 我相信这是我需要的东西,但如果输出类似于 chinese>
        • 然后您需要查看 DomDocument 类集。那些更适合。在这种情况下,我们正在谈论获取节点的属性。使用 DomDocument 时,您可以通过标记名获取节点。一旦你拥有那些是php.net/manual/en/class.domnode.php 对象的节点,你就可以获得这些节点的属性。检查php.net/manual/en/domdocument.getelementsbytagname.php 并阅读它返回的 DomNodeList。该列表又包含 DomNode 对象。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 1970-01-01
        • 1970-01-01
        • 2019-01-23
        • 2021-11-05
        • 1970-01-01
        相关资源
        最近更新 更多