Link to home
Create AccountLog in
Avatar of Richard Winnick
Richard Winnick

asked on

php parse xml post to database

Hi -
I am a beginner with xml and moderately comfortable with PHP -
I have been trying to make this work for longer than you would believe -
and am totally confused after all the articles and posts I have read about xml -
and I am obviously still missing something -

A third party provider is posting the following xml string to me -

<?xml version=\1.0\" encoding=\"utf-8\" ?><IvrData><TemplateID>21</TemplateID><QueueID>634257052820310008</QueueID><Attempt>2</Attempt><CallTime>2010-11-18T19:42:11-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>8</ReferenceID><Items><Item id=\"1\" value=\"1\" variable=\"JXC9B9MQDK-2-8-1\" /><Item id=\"2\" value=\"2\" variable=\"BXK7MZDNZQ-2-8-2\" /></Items></IvrData>

The xml string can have several item id tags with their value and variable name attributes -
I need to parse the xml and put the Item id's with their values and variable names into my MYSQL database -

I have been able to 'grab' the entire xml string using $Data = $_POST["Data"]
But I have been unable to parse the contents of the $Data variable -

I have tried using simplexml_load_string($Data)
But there doesn't seem to be anything there -

Thanks in advance for any help -
and please remember I'm just starting with xml :-)
Richard
Avatar of hpierson
hpierson

This simple program:

<?php
$Data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><IvrData><TemplateID>21</TemplateID><QueueID>634257052820310008</QueueID><Attempt>2</Attempt><CallTime>2010-11-18T19:42:11-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>8</ReferenceID><Items><Item id=\"1\" value=\"1\" variable=\"JXC9B9MQDK-2-8-1\" /><Item id=\"2\" value=\"2\" variable=\"BXK7MZDNZQ-2-8-2\"/></Items></IvrData>";
$xml = simplexml_load_string($Data);
print_r($xml);
?>

Open in new window


Outputs :


SimpleXMLElement Object
(
    [TemplateID] => 21
    [QueueID] => 634257052820310008
    [Attempt] => 2
    [CallTime] => 2010-11-18T19:42:11-05:00
    [Telephone] => 2072655421
    [CallResult] => PVD
    [ReferenceID] => 8
    [Items] => SimpleXMLElement Object
        (
            [Item] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [@attributes] => Array
                                (
                                    [id] => 1
                                    [value] => 1
                                    [variable] => JXC9B9MQDK-2-8-1
                                )
 
                        )
 
                    [1] => SimpleXMLElement Object
                        (
                            [@attributes] => Array
                                (
                                    [id] => 2
                                    [value] => 2
                                    [variable] => BXK7MZDNZQ-2-8-2
                                )
 
                        )
 
                )
 
        )
 
)

Open in new window

You need to realize that

$xml = simplexml_load_string($Data);

Creates an SimpleXML object. You want to look at this page to understand how to access it as a tree

See:

http://us2.php.net/manual/en/book.simplexml.php
http://us2.php.net/manual/en/class.simplexmlelement.php
http://us2.php.net/manual/en/simplexmlelement.children.php

You can also find functions to convert SimpleXML objects to nested arrays, see Julio Cesar Oliveira on::

http://us2.php.net/manual/en/function.simplexml-load-string.php

//The XML2Array func now Recursive!

<?php
function XML2Array ( $xml , $recursive = false )
{
    if ( ! $recursive )
    {
        $array = simplexml_load_string ( $xml ) ;
    }
    else
    {
        $array = $xml ;
    }
    
    $newArray = array () ;
    $array = ( array ) $array ;
    foreach ( $array as $key => $value )
    {
        $value = ( array ) $value ;
        if ( isset ( $value [ 0 ] ) )
        {
            $newArray [ $key ] = trim ( $value [ 0 ] ) ;
        }
        else
        {
            $newArray [ $key ] = XML2Array ( $value , true ) ;
        }
    }
    return $newArray ;
}
?>

Open in new window


If you do simplexml_load_string($Data) and you get "nothing" you probably had invalid (unparseable) XML and the function returned FALSE.
I ran this script (copying the data from the post above with cut-paste)  What a mess!  The quotes are not balanced, and it makes quite a hash of the data string.
<?php /// RAY_temp_rwinnick.php
error_reporting(E_ALL);
echo "<pre>" . PHP_EOL;

// TEST DATA FROM THE POST AT EE
$xml = <<<XML
<?xml version=\1.0\" encoding=\"utf-8\" ?><IvrData><TemplateID>21</TemplateID><QueueID>634257052820310008</QueueID><Attempt>2</Attempt><CallTime>2010-11-18T19:42:11-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>8</ReferenceID><Items><Item id=\"1\" value=\"1\" variable=\"JXC9B9MQDK-2-8-1\" /><Item id=\"2\" value=\"2\" variable=\"BXK7MZDNZQ-2-8-2\" /></Items></IvrData>
XML;

// WE DO NOT NEED THESE EXTRA ESCAPE SLASHES
$xml = stripslashes($xml);
var_dump($xml);

// MAKE AN OBJECT
$obj = SimpleXML_Load_String($xml);
var_dump($obj);

Open in new window

This worked much better.

<?php /// RAY_temp_rwinnick.php
error_reporting(E_ALL);
echo "<pre>" . PHP_EOL;

// TEST DATA FROM THE POST AT EE
$xml = <<<XML
<?xml version=\"1.0\" encoding=\"utf-8\" ?><IvrData><TemplateID>21</TemplateID><QueueID>634257052820310008</QueueID><Attempt>2</Attempt><CallTime>2010-11-18T19:42:11-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>8</ReferenceID><Items><Item id=\"1\" value=\"1\" variable=\"JXC9B9MQDK-2-8-1\" /><Item id=\"2\" value=\"2\" variable=\"BXK7MZDNZQ-2-8-2\" /></Items></IvrData>
XML;

// WE DO NOT NEED THESE EXTRA ESCAPE SLASHES
$xml = stripslashes($xml);
var_dump($xml);

// MAKE AN OBJECT
$obj = SimpleXML_Load_String($xml);
var_dump($obj);

Open in new window

Install this and run it to see the pattern, then post back with any questions.  Best of luck with your project, ~Ray
<?php /// RAY_temp_rwinnick.php
error_reporting(E_ALL);
echo "<pre>" . PHP_EOL;

// TEST DATA FROM THE POST AT EE
$xml = <<<XML
<?xml version=\"1.0\" encoding=\"utf-8\" ?><IvrData><TemplateID>21</TemplateID><QueueID>634257052820310008</QueueID><Attempt>2</Attempt><CallTime>2010-11-18T19:42:11-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>8</ReferenceID><Items><Item id=\"1\" value=\"1\" variable=\"JXC9B9MQDK-2-8-1\" /><Item id=\"2\" value=\"2\" variable=\"BXK7MZDNZQ-2-8-2\" /></Items></IvrData>
XML;

// WE DO NOT NEED THESE EXTRA ESCAPE SLASHES
$xml = stripslashes($xml);
var_dump($xml);

// MAKE AN OBJECT
$obj = SimpleXML_Load_String($xml);
var_dump($obj);

echo PHP_EOL;

foreach ($obj->Items->Item as $thing)
{
    $id = (string)$thing["id"];
    $vl = (string)$thing["value"];
    $vr = (string)$thing["variable"];

    echo PHP_EOL
    . " ID "
    . $id
    . " VALUE "
    . $vl
    . " VAR "
    . $vr
    ;
}

Open in new window

Avatar of Richard Winnick

ASKER

Hi Ray -
Thanks for the quick response -
I have installed and run your example and it works great -
My question now is how do I get the "raw" xml that is posted to me into the $xml variable so that I can use it with the stripslashes() and SimpleXML_Load_String(xml) as you have demonstrated -

If I try posting the sample xml from my original post to the file that contains your script via a form that I have created with a Method of POST and  try to use -
$xml = $_POST["Data"];
rather than the $xml you have written in the script it doesn't work -

I know I'm probably missing something simple but this is where I get hung up -
Thanks again for the quick reply and looking forward to your next post -
I really want to learn how to do this -
Richard
Glad to help.  Here is what I need to see at this point.  You have a script that receives the POST from a foreign site.  Go into that script and add this code to send an email to yourself.  It will show us what is in the POST array.
<?php // UNTESTED CODE BUT VALID IN PRINCIPLE

// COLLECT INFO IN A BUFFER
ob_start();
echo "<pre>";
var_dump($_POST);
$msg = ob_get_clean();

// EMAIL THIS INFORMATION TO YOURSELF
mail('you@your.org', 'POST DATA', $msg);

Open in new window

Hi Ray -
That is so cool :-)
I've been going crazy trying to figure out how to 'see' what was being sent to me -
The following is the email I received from your script of an actual post from the third party provider -
Richard

<pre>array(3) {
  ["Data"]=>
  string(347) "<?xml version="1.0" encoding="utf-8"
?><IvrData><TemplateID>28</TemplateID><QueueID>634296438473650008</QueueID><
Attempt>1</Attempt><CallTime>2011-01-03T09:30:05-05:00</CallTime><Telephone>
2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>33</Reference
ID><Items><Item id="1" value="5" variable="6CH4JQDYO5-2-33-1"
/></Items></IvrData>"
  ["QueueID"]=>
  string(18) "634296438473650008"
  ["Duration"]=>
  string(2) "30"
}
Excellent!  Now we can make progress.  I will set up a simulation for you.

<?php // RAY_temp_rwinnick.php
error_reporting(E_ALL);
echo "<pre>";

// A SIMULATION OF THE POST DATA
$_POST
= array
( "Data"     => '<?xml version="1.0" encoding="utf-8"?><IvrData><TemplateID>28</TemplateID><QueueID>634296438473650008</QueueID><Attempt>1</Attempt><CallTime>2011-01-03T09:30:05-05:00</CallTime><Telephone>2072655421</Telephone><CallResult>PVD</CallResult><ReferenceID>33</ReferenceID><Items><Item id="1" value="5" variable="6CH4JQDYO5-2-33-1"/></Items></IvrData>'
, "QueueID"  => "634296438473650008"
, "Duration" => "30"
)
;

// DOES IT LOOK RIGHT?  CLOSE ENOUGH
// var_dump($_POST);

// MAKE AN OBJECT FROM THE XML
$obj = SimpleXML_Load_String($_POST["Data"]);
var_dump($obj);

// SHOW HOW TO ACCESS THE POST DATA AND THE OBJECT PROPERTIES
echo PHP_EOL . "POST['QueueID'] " . $_POST["QueueID"];
echo PHP_EOL . "XML->QueueID    " . $obj->QueueID;

// SHOW HOW TO USE AN ITERATOR TO ACCESS THE ATTRIBUTES OF THE ITEMS
foreach ($obj->Items->Item as $i)
{
    echo PHP_EOL . "id " . $i["id"];
    echo PHP_EOL . "variable " . $i["variable"];
}

Open in new window

Hi Ray -
Wow - works like a charm -
After initial testing I took out the 'simulated' xml and used the $POST["Data"] and initiated another actual post from the provider and it still worked !!!
Guess I am getting the hang of how it fits together :-)
I can see how the 'foreach' echo's the id and variable values - but -
How would I use the 'foreach' to assign the id and variable values to variables so that I can use them in an SQL statement to insert them into my database - since I don't know ahead of time how many 'item id's' there will be in the xml post -
I'm comfortable with doing the SQL insert once I have the values as variables -
I can't believe how much progress we've made so quickly -
and you wouldn't believe how many days/hours I've been trying to make this work :-)
Amazing what can be done if you have a good 'teacher' -
Richard
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Hi Ray -
Amazing -
assigned properties to strings as you suggested -
made insert SQL part of the 'foreach' -
initiated new post which had two 'item id's' in it -
all info showed up appropriately in database -

and we did it all this AM -
I can't thank you enough -
Not only do I have working code -
I also gained significant insights into how and why this all works -
It has really helped to clarify all the reading I had done that had me so confused -
Thanks again and I'll accept the solution -
Have a Happy and Prosperous New Year -
See you next time :-)
Richard

Glad you got it sorted out.  Usually at EE when you get good answers, it is considered appropriate to accept one or more of the answers.  That process awards points to the experts who helped.  I don't know if you meant to close the question with zero points, but it looks like that is pending now.  If you decide you want to give me the points, you can probably get a moderator to reopen this Q.

Happy new year, ~Ray
made mistake clicked wrong button - wanted to awarded 500 points and comment to Ray Passeur -
Please fix -
Sorry
Richard
major help - think I got the right accept this time
Thanks for the points -- it's a great question.  

Best regards, ~Ray
Hi Ray -
sorry for the screw up - but looks like OK now -
Have a great New Year -
You sure got mine off to a SUPER start :-)
R
Yep!  Thanks, ~Ray