【问题标题】:Retrieve keys from xml in php在 php 中从 xml 中检索密钥
【发布时间】:2021-10-24 02:39:42
【问题描述】:

我需要获取 xml 中的所有节点键。我转换为数组,然后用下面的代码完成,

<?php
$array='<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<country>
    <id>18</id>
    <id_zone xlink:href="https://www.example.com/api/zones/299">299</id_zone>
    <id_currency>0</id_currency>
    <call_prefix>469</call_prefix>
    <iso_code>SE</iso_code>
    <active>1</active>
    <contains_states>0</contains_states>
    <need_identification_number>0</need_identification_number>
    <need_zip_code>1</need_zip_code>
    <zip_code_format>NNN NN</zip_code_format>
    <display_tax_label>1</display_tax_label>
    <name><language id="1" xlink:href="https://www.example.com/api/languages/1">Suède</language><language id="2" xlink:href="https://www.example.com/api/languages/2">Sweden</language></name>
</country>
</prestashop>';
$array1=json_decode(json_encode((array)simplexml_load_string($array,'SimpleXMLElement',LIBXML_NOCDATA)),1);
//print_r($array1);die();
function getUniqueObjectKeyPaths(array $array, $parentKey = "") {
    $keys = [];
    foreach ($array as $parentKey => $v) {
        if (!is_numeric($parentKey) && !is_array($v)) {
            $keys[] = $parentKey;
        }
        if (is_array($v)) {
            $nestedKeys = getUniqueObjectKeyPaths($v, $parentKey);
            foreach($nestedKeys as $index => $key) {
                if (!is_numeric($parentKey) && !is_numeric($key)) {
                    $nestedKeys[$index] = $parentKey . "->" . $key;
                }
            }
            $keys = array_merge($keys, $nestedKeys);
        }
    }
    return $keys;
}
$k=getUniqueObjectKeyPaths($array1);
print_r($k);

我得到的结果如下,

Array ( 
    [0] => country->id 
    [1] => country->id_zone 
    [2] => country->id_currency 
    [3] => country->call_prefix 
    [4] => country->iso_code 
    [5] => country->active 
    [6] => country->contains_states 
    [7] => country->need_identification_number 
    [8] => country->need_zip_code 
    [9] => country->zip_code_format 
    [10] => country->display_tax_label 
)

预期的结果是,

我还需要key country->name->language->0,country->name->language->1.

任何快速帮助将不胜感激。

谢谢, 雷卡

【问题讨论】:

    标签: php xml


    【解决方案1】:

    您使用递归函数走在正确的轨道上。您需要将$keys 作为函数参数添加到$parentKey 旁边。

    function getUniqueObjectKeyPaths(array $array, $parentKey = '', $keys = [])
    {
        foreach ($array as $key => $value) {
            if (!empty($parentKey))
                $key = $parentKey . '->' . $key;
    
            if (is_array($value))
                return getUniqueObjectKeyPaths($value, $key, $keys);
    
            $keys[] = $key;
        }
        return $keys;
    }
    

    【讨论】:

      【解决方案2】:

      我认为不需要 json_decode(json_encode()) 东西并将 SimpleXMLElement 转换为数组也会添加 [@attributes] 索引。您可以自行遍历SimpleXMLElement 对象:

      功能:

      function getUniqueObjectKeyPaths(SimpleXMLElement $el, array $trail = []) : array {
        // intialize collected paths
        $paths = [];
        
        // keep track of identically named children
        $sameNameIndices = [];
        foreach($el as $child) {
          // store child's name
          $name = $child->getName();
          
          // we can count how may identically named children with $name there are in element by using count($el->childName)
          // and with the special syntax $el->{$name} we can use the name stored in the variabel $name
          $sameNameCount = count($el->{$name});
          
          // if we have multiple identically named children...
          if($sameNameCount > 1) {
            // initialize or increment identically named child index
            $sameNameIndices[$name] = !isset($sameNameIndices[$name]) ? 0 : $sameNameIndices[$name] + 1;
          
            // add name with its index to trail
            $trail[] = $name . '->' . $sameNameIndices[$name];
          }
          // else...
          else {
            // only add name
            $trail[] = $name;
          }
          
          // since we only want leaves, recurse if this child has children of its own
          if(count($child)) {
            // push recursed paths to our local paths collection
            array_push($paths, ...getUniqueObjectKeyPaths($child, $trail));
          }
          // else add our path to the paths collection
          else {
            $paths[] = implode('->', $trail);
          }
          
          // remove name from the trail again
          array_pop($trail);
        }
        
        // return collected paths
        return $paths;
      }
      

      用法:

      
      $xml = '<?xml version="1.0" encoding="UTF-8"?>
      <prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
        <country>
            <id>18</id>
            <id_zone xlink:href="https://www.example.com/api/zones/299">299</id_zone>
            <id_currency>0</id_currency>
            <call_prefix>469</call_prefix>
            <iso_code>SE</iso_code>
            <active>1</active>
            <contains_states>0</contains_states>
            <need_identification_number>0</need_identification_number>
            <need_zip_code>1</need_zip_code>
            <zip_code_format>NNN NN</zip_code_format>
            <display_tax_label>1</display_tax_label>
            <name>
              <language id="1" xlink:href="https://www.example.com/api/languages/1"><test>Suède</test></language>
              <test id="2" xlink:href="https://www.example.com/api/languages/2">Sweden</test>
              <language id="2" xlink:href="https://www.example.com/api/languages/2">Sweden</language>
            </name>
        </country>
      </prestashop>';
      
      $el = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
      
      print_r(getUniqueObjectKeyPaths($el));
      

      ...打印:

      Array
      (
          [0] => country->id
          [1] => country->id_zone
          [2] => country->id_currency
          [3] => country->call_prefix
          [4] => country->iso_code
          [5] => country->active
          [6] => country->contains_states
          [7] => country->need_identification_number
          [8] => country->need_zip_code
          [9] => country->zip_code_format
          [10] => country->display_tax_label
          [11] => country->name->language->0
          [12] => country->name->language->1
      )
      

      【讨论】:

      • 这很完美。谢谢。在某些情况下,我还需要获取 id 属性值 ie.country->name->language->0->id ,这也是我需要的。
      猜你喜欢
      • 1970-01-01
      • 2011-01-11
      • 2017-03-05
      • 2017-12-31
      • 2017-06-09
      • 2017-02-12
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多