Avatar of Phonebuff
Flag for United States of America asked on

Need help with parsing XML file into CSV format using a PHP script -

I am trying to build a PHP script to parse a rather complex XML document and output CSV data for certain names spaces within the document - But my simple code just to get the basic construct decoded is not working.  This is my first effort in this space hope someone here might see the error of my ways and help a little -- 

My Code looks like this right now -- Generating 

L1 config L2 category L3 set L4 collection L5 set L5  

$filexml='contacts_20211226.xml';     if (file_exists($filexml))            {     echo "File name: ", $filexml ;     echo "\n" ;        $xml = simplexml_load_file($filexml);        if ($xml === false) {         echo "Failed loading XML: ";          foreach(libxml_get_errors() as $error) {          echo $error->message;          echo "\n" ;          }        }        $f = fopen('test.csv', 'w');        createCsv($xml, $f);        fclose($f);     } else {     echo "No File name: ", $filexml ;     echo "\n" ;     }     function createCsv($xml,$f)
        $l1Name = $xml->getName() ;         echo 'L1 ' . $l1Name ;         echo "\n" ;         foreach ($xml->children() as $second_gen) {         $l2Name = $second_gen->getName() ;             echo 'L1 ' . $l1Name ;                  ' L2 ' . $l2Name ;             echo "\n" ;             foreach ($second_gen->children() as $third_gen) {                 $l3Name = $third_gen->getName() ;                 echo 'L1 ' . $l1Name ;                      ' L2 ' . $l2Name ;                      ' L3 ' . $l3Name ;                 echo "\n" ;                 foreach ($third_gen->children() as $fourth_gen) {                 $l4Name = $fourth_gen->getName() ;                     echo 'L1 ' . $l1Name .                          ' L2 ' . $l2Name .                          ' L3 ' . $l3Name .                          ' L4 ' . $$l4name ;                     echo "\n" ;                         foreach ($fourth_gen->children() as $fifth_gen) {                         $l5Name = $fifth_gen->getName() ;                             echo 'L1 ' . $l1Name .                                  ' L2 ' . $l2Name .                                  ' L3 ' . $l3Name .                                  ' L4 ' . $l4Name .                                  ' L5 ' . $l5Name .                                  ' L5 ' . $fifth_gen ;                             echo "\n" ;                         }                 }             }          }     } ?>

Open in new window

  But this will not output the that I expect --- For example -- 

I get this as output But never see the values in name=" " or the actual data elements.

L1 config L2 category L3 set L4  where as I would like to see 

L1 config L2 catergory "PCRContacts" L3 set "PCRContacts" alias "Talk-around"  L4 field .......... L5 collection ....  

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
L1 = <config>
L2 =   <category name="PCRContacts">

L3 =     <set name="PCRContacts" alias="Talk-around">
L4 =      <field name="ContactName">Talk-around</field>

L5 =       <collection name="MDCCalls" />
L5 =       <collection name="QuikCallIICalls" />
L5 =      <collection name="DigitalCalls">
L6 =        <set name="DigitalCalls" index="0" key="GRPCALL">:q!
 L7 =           <field name="DU_CALLALIAS">Talk-around</field>
          <field name="DU_CALLLSTID">10000</field>
          <field name="DU_ROUTETYPE" Name="Regular">REGULAR</field>
          <field name="DU_CALLPRCDTNEN">False</field>
          <field name="DU_RINGTYPE" Name="No Style">NOSTYLE</field>
          <field name="DU_TXTMSGALTTNTP" Name="Repetitive">REPETITIVE</field>
          <field name="DU_CALLTYPE" Name="Group Call">GRPCALL</field>
          <field name="DU_OVCMCALL">False</field>
          <field name="DU_CALLTYPEPART2">0</field>
          <field name="DU_UKPOTCFLG">False</field>
          <field name="DU_RVRTPERS_Zone" Name="None">NONE</field>
          <field name="DU_RVRTPERS" Name="Selected">SELECTED</field>
          <field name="CallType">Digital Calls-Group Call</field>
          <field name="PeudoCallId">10000</field>
 L6 =       </set>
 L5 =     </collection>
      <collection name="CapacityPlusCalls" />
      <collection name="PhoneCalls" />
      <field name="Comments"></field>


Avatar of undefined
Last Comment

8/22/2022 - Mon
David Johnson, CD


David,  am I missing something -- I thought I did start by pulling the file into the array $xml.

  -- $xml = simplexml_load_file($filexml);
The problem I seem to have is processing each element of the array with the Children(), getName() and some function I don't seem to be aware of to get the various parts of the line. Maybe I should forget it's XML and just use an awk script to take it apart.  Also, it might be more HTML than XML the more I look at it.
Chris Stanyon

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question



    THANK YOU --  That all makes sense. One question in my mind before I go try and take this object apart again, is there any way through the functions available to know that I am working Level 3 verses Level 6 in the tree ??  

    As to where I am trying to get to, buried n levels into this document is some data that I am trying to extract to reconcile against an LDAP for the organization.  It's been done by hand previously but it is time to try and automate it and by doing so reconcile more often !  

I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Chris Stanyon

No worries :)

Firstly, not really. The concept of Levels doesn't usually apply to XML - that's just something that you've called it. I guess technically, you could keep track of it, as you drop further down the tree. You could also call the xpath method with parent to work out where you're at.

The more standardised your XML document is, the easier it will be to code. If you KNOW for certain that the data you need will ALWAYS be in a given Node, then you can generally access it directly, eiter through object properties, or with xpath expressions.

For example:

// Object Properties
// Loop through the children of the <set name="PCRContacts"> node
foreach ($xml->category[0]->set->children() as $element) {
  echo $element->getName() . '|' . $element['name'] . PHP_EOL;

// XPath
// Loop through all the <field> elements that are children of the <set name="DigitalCalls"> node
$fields = $xml->xpath("//config/category/set/collection/set[@name='DigitalCalls']/field");
foreach ($fields as $field) {
  echo $field['name'] . '|' . $field . PHP_EOL;

Open in new window



Thank you --  Will look at this over the Holiday Weekend..  

Happy, Safe and Healthy New year !



    I am almost there -- But how do I test for the presence of a value --

"To read the value, you just output the variable"  works fine if there is a value such as -
  <field name="ContactName" alias="SomethingElse">Talk-around</field>  

But if there is no value, I get garbage in the echo. I thought that either isset() or is_string() would be the answer but neither seem to help in determining when there is a value verses no value in the XML statement such as -
  <collection name="MDCCalls" />



Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.