1

Trying to find a way to read an XML file and get all the nodes. Some of the XML files have 1 step depth, others 2, others more. Is there anyway to get all the nodes for all children without knowing their name? e.g. i wrote this piece of code but this works only for 2 steps depth

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>
10
  • Please share your xml string. Commented May 11, 2017 at 9:15
  • @SahilGulati i've added to my question Commented May 11, 2017 at 9:25
  • Which information you want to extract? Commented May 11, 2017 at 9:25
  • i must get all the nodes names. e.g. username, password,clientid, transtype, company, product, p_year etc and all the attributes names (e.g. SVCsynchronouscall, value1 etc) Commented May 11, 2017 at 9:37
  • Hope my post will help you out.. Commented May 11, 2017 at 10:15

1 Answer 1

2

Here we are using DOMDocument and DOMXPath to find the innerHTML of soap:Body. And then we treating innerHTML in simplexml_load_string and converting it into array using json_encode and json_decode, and finally we are using array_walk_recursive to get all values.

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));

output:

 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
        )
)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.