Search code examples
phpxmlsimple-html-dom

How to get Multilevel tag from SOAP Message and make array using simpledomhtml in PHP


I have problem in code, when i parse XML to Array get single array of XML.Actually I want to parse all soap v1.2 response message in array/json.and fetch multiple array if exits, For example multiple data in array exist in array and wrapped single array according to give expected output.

Here is my code:

data.txt file

    <?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="<a rel="nofollow" class="external free" href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/</a>"
  xmlns="urn:enterprise.soap.sforce.com">
  <soapenv:Body>
        <getResponse>
            <result xsi:type="sf:sObject">
             <id>123</id>
             <description>description</description>
             <name>testing</name>
             <cnic>23198398213</cnic>
          </result>
         <result xsi:type="sf:sObject">
             <id>567</id>
             <description>LOrem ipsum des</description>
             <name>name testing</name>
             <cnic>2827489024243</cnic>
          </result>
        </getResponse>
  </soapenv:Body>
</soapenv:Envelope>

My PHP code:

<?php
    ini_set("memory_limit", "44879M");
    include("dom.php");
    $xml = str_get_html( file_get_contents("data.txt") );
    $final = array();
    $result = $xml->find("result");
    foreach($result as $r){
        $tag = $r->children();
        $one = array();
        foreach($tag as $child){
            $tag = $child->tag;
            echo "<pre>";
            print_r($tag); echo "<br>";

            if( stristr($tag, ":") ){
                list($com, $tag) = explode(":", $tag);
            }
            $one[$tag]  =  trim(strip_tags($child->innertext));
        }
        $final[] = $one;
    }
    print_r($final);
?>

My expected output should:

Array
(
   [getResponse] => Array(
       [result]=> Array(
          [0] =>  Array(
               [id] => 123
               [description] => description
               [name] => testing   
               [cnic] =>   23198398213       
             )
          [1] =>  Array(
               [id] => 567
               [description] => LOrem ipsum des
               [name] => name testing
               [cnic] =>   2827489024243
             )
           )

        )
)

Please help

Thanks in Advance.


Solution

  • You would best of using a recursive solution to pass a hierarchy into an array. This code starts off with each element and if there are any sub-nodes, then it calls the same routine again to build the data for that sub set of data.

    require_once "dom.php";
    
    function xmlToArray ( simple_html_dom_node $base )  {
        $newData = [];
        foreach ( $base->children as $newElement )  {
            if ( $newElement->has_child() === true ) {
                $addData = xmlToArray($newElement);
                // if element already exists
                if ( isset($newData [ $newElement->tag ]) ) {
                    // if not already a list of elements
                    if ( !isset($newData [ $newElement->tag ][0])) {
                        // Turn into an array of elements
                        $newData [ $newElement->tag ] = [$newData [ $newElement->tag ]];
                    }
                    // Add data to end
                    $newData [ $newElement->tag ][] = $addData;
                }
                else    {
                    $newData [ $newElement->tag ] = $addData;
                }
            }
            else    {
                $newData [ $newElement->tag ] = $newElement->innertext;
            }
        }
        return $newData;
    }
    $xml = str_get_html( file_get_contents("data.txt") ); 
    $final = xmlToArray ( $xml->root->find("soapenv:Body")[0] );
    print_r($final);
    

    The recursive routine is started with the content of the <soapenv:Body> tag and then processes this content.

    This outputs...

    Array
    (
        [getresponse] => Array
            (
                [result] => Array
                    (
                        [id] => 123
                        [description] => description
                        [name] => testing
                        [cnic] => 23198398213
                    )
    
            )
    
    )
    

    I would still recommend to look into using SimpleXML or DOMDocument, but this should work with what you already have.