PHP从嵌套的XML字符串中检索所有节点名称和节点值

时间:2017-05-11 09:13:12

标签: php xml simplexml

试图找到一种方法来读取XML文件并获取所有节点。 一些XML文件具有1步深度,其他2个,其他更多。 无论如何,在不知道名字的情况下为所有孩子获取所有节点? 例如我写了这段代码,但这只适用于2步深度

foreach ($xml->children() as $node) {
        if ($node->children()->count()>0) {
            foreach ($node->children() as $cnode){
                echo $cnode->getName()."<br>";
            }
        }
        echo $node->getName()."<br>";
    }
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" >
   <soap:Header/>
   <soap:Body>
      <multitrans xmlns="http://www.xxxx.xx/">
         <authentication>
            <username>xxxxxx</username>
            <password>xxxxxx</password>
            <clientid>xxxxxx</clientid>
         </authentication>
         <requests>
            <trans_request>
               <TransType tc="100"/>
               <company tc="500"/>
               <product tc="auto"/>
               <inception>
                  <p_year>2017</p_year>
                  <p_month>5</p_month>
                  <p_day>15</p_day>
               </inception>
               <p_number>0</p_number>
               <attributes>
                              <att val="0" name="SVCsynchronouscall" />
                              <att val="2" name="value1" />
                              <att val="2017-5-15" name="Date" />
                              <att val="0" name="value2" />
                              <att val="0" name="value3" />
                              <att val="0" name="value4" />
               </attributes>
<warnings>

</warnings>
            </trans_request>
         </requests>
      </multitrans>
   </soap:Body>
</soap:Envelope>

1 个答案:

答案 0 :(得分:1)

我们正在使用DOMDocumentDOMXPath来查找soap:Body的innerHTML。然后我们处理innerHTML中的simplexml_load_string并使用json_encodejson_decode将其转换为数组,最后我们使用array_walk_recursive来获取所有值。

Try another code snippet here Demo for simple xml not-nested

Try this code snippet here Demo for nested xml

$string = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" >
   <soap:Header/>
   <soap:Body>
      <multitrans xmlns="http://www.xxxx.xx/">
         <authentication>
            <username>xxxxxx</username>
            <password>xxxxxx</password>
            <clientid>xxxxxx</clientid>
         </authentication>
         <requests>
            <trans_request>
               <TransType tc="100"/>
               <company tc="500"/>
               <product tc="auto"/>
               <inception>
                  <p_year>2017</p_year>
                  <p_month>5</p_month>
                  <p_day>15</p_day>
               </inception>
               <p_number>0</p_number>
               <attributes>
                  <att val="0" name="SVCsynchronouscall" />
                  <att val="2" name="value1" />
                  <att val="2017-5-15" name="Date" />
                  <att val="0" name="value2" />
                  <att val="0" name="value3" />
                  <att val="0" name="value4" />
               </attributes>
            <warnings>
            </warnings>
            </trans_request>
         </requests>
      </multitrans>
   </soap:Body>
</soap:Envelope>';
 $finalResult = array();
$domObject = new DOMDocument();
$domObject->loadXML($string);

$domXPATH = new DOMXPath($domObject);
$results = $domXPATH->query("//soap:Body/*");

foreach($results as $result)
{
    if($result->childNodes->length==1 && $result->childNodes->item(0) instanceof  DOMText)
    {
        $finalResult[$result->tagName] = $result->textContent;
    }
    else
    {
        $array = json_decode(json_encode(simplexml_load_string($result->ownerDocument->saveXML($result))), true);
        array_walk_recursive($array, function($value,$key) use(&$finalResult)
        {
            if (!empty($value))
            {
                if(isset($finalResult[$key])&& is_string($finalResult[$key]) )
                {
                    $temp=$finalResult[$key];
                    $finalResult[$key] = array($temp,$value);
                }
                elseif(isset($finalResult[$key]) && is_array($finalResult[$key]) && count($finalResult[$key])>0)
                {
                    $finalResult[$key]=  array_merge(array($value),$finalResult[$key]);
                }
                else
                {
                    $finalResult[$key]=$value;
                }
            }
        });        
    }

}
print_r(array_filter($finalResult));

<强>输出:

 Array
(
    [username] => xxxxxx
    [password] => xxxxxx
    [clientid] => xxxxxx
    [tc] => Array
        (
            [0] => auto
            [1] => 100
            [2] => 500
        )

    [p_year] => 2017
    [p_month] => 5
    [p_day] => 15
    [name] => Array
        (
            [0] => value4
            [1] => value3
            [2] => value2
            [3] => Date
            [4] => SVCsynchronouscall
            [5] => value1
        )

    [val] => Array
        (
            [0] => 2
            [1] => 2017-5-15
        )
)