Reading an XML Post

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

kevin7654
Forum Newbie
Posts: 19
Joined: Sat Feb 18, 2006 2:38 pm

Reading an XML Post

Post by kevin7654 »

Hey everyone,

My shipping company posts an xml file to my web server. How do I go about parsing and reading this file to extract the information from it? I'm completely lost and have no idea where to begin. I've tried reading a bit about xml and the built in php functions but they all seem to tell me how to take a url or a file and read that, but how do I tell my scrip it is coming from a post?

Thanks,
Kevin

Here's an example of the xml file:

Code: Select all

<Status AffiliateID="CP" OrderID="12345">
&#8722;
	<Shipment PackageID="98765" Status="Shipped" ShipDate="2001-08-07 12:14:27.0" TrackingNumber="1ZY9W6270241234173">
<ShipMethod>FedEx-2 Day</ShipMethod>
<Item ItemID="98765-1"/>
<Item ItemID="98765-2"/>
<Item ItemID="98765-3"/>
<Item ItemID="98765-4"/>
<Item ItemID="98765-5"/>
<Item ItemID="98765-6"/>
</Shipment>
&#8722;
	<Shipment PackageID="56789" Status="Shipped" ShipDate="2001-08-07 14:41:25.0">
<ShipMethod>USPS-First Class</ShipMethod>
<Item ItemID="56789-1"/>
<Item ItemID="56789-2"/>
<Item ItemID="56789-4"/>
</Shipment>
&#8722;
	<Shipment PackageID="56789" Status="Processing" ShipDate="">
<ShipMethod>USPS-First Class</ShipMethod>
<Item ItemID="56789-3"/>
</Shipment>
&#8722;
	<Shipment PackageID="56789" Status="Cancelled" ShipDate="">
<ShipMethod>USPS-First Class</ShipMethod>
<Item ItemID="56789-4"/>
<Item ItemID="56789-5"/>
</Shipment>
</Status>
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

Try this:

Code: Select all

$file = "tst1.xml";
function trustedFile($file)
{
	return true;
}
function startElement($parser, $name, $attribs)
{
	echo "<";
	echo "<font color=\"#0000cc\">$name</font>";
	if (count($attribs))
	{
		foreach ($attribs as $k => $v)
		{
			echo " <font color=\"#009900\">$k</font>=\"<font color=\"#990000\">$v</font>\"";
		}
	}
	echo ">";
}
function endElement($parser, $name)
{
	echo "</<font color=\"#0000cc\">$name</font>>";
}

function new_xml_parser($file)
{
	global $parser_file;
	$xml_parser = xml_parser_create();
	xml_set_element_handler($xml_parser, "startElement", "endElement");
	xml_set_character_data_handler($xml_parser, "characterData");
	if (!($fp = @fopen($file, "r")))
	{
		return false;
	}
	if (!is_array($parser_file))
	{
		settype($parser_file, "array");
	}
	$parser_file[$xml_parser] = $file;
	return array($xml_parser, $fp);
}

if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
   die("could not open XML input");
}
echo "<pre>";
while ($data = fread($fp, 4096))
{
	if (!xml_parse($xml_parser, $data, feof($fp)))
	{
		die(sprintf("XML error: %s at line %d\n",xml_error_string(xml_get_error_code($xml_parser)),                  xml_get_current_line_number($xml_parser)));
	}
}
echo "</pre>";
echo "parse complete\n";
xml_parser_free($xml_parser);
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Re: Reading an XML Post

Post by timvw »

kevin7654 wrote: but how do I tell my scrip it is coming from a post?

Code: Select all

$data = file_get_contents('php://input');
(I don't remember if this also includes the headers, so you might want to chop them off first....)
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

what exactly is the process of your application? can you please tell me how you are requesting and what is the response type?
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

You can parse a xml string to a dom with simplexml_load_string().
It doesn't matter where or why this string was created.

Code: Select all

$xml = simplexml_load_string($data);
foreach($xml->Shipment as $shipment) {
	echo '<pre>';
	echo ' packageId: ', $shipment['PackageID'], "\n",
		' Status: ', $shipment['Status'], "\n",
		' ShipDate: ', $shipment['ShipDate'], "\n",
		' TrackingNumber: ', $shipment['TrackingNumber'], "\n";
	foreach($shipment->Item as $item) {
		echo '  ItemId: ', $item['ItemID'], "\n";
	}
	echo "</pre>\n";
}
timvw wrote:

Code: Select all

$data = file_get_contents('php://input');
This will provide you the complete request body data. If the xml data is sent without further encoding/methods then this is a good way to get the data.
If the xml input you get is huge you might need a sax parser like itsmani1 has provided. Otherwise I would stick with the much simpler dom.
Now it dependes on exactly how
kevin7654 wrote:My shipping company posts an xml file to my web server.
is done .
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

volka in my case i am getting data form a file, Here i have question if i am not getting data form the file instead i am getting it as a result of a function call like:

Code: Select all

$data = myCall(..,..,..)
and now my whole xml is in my $data variable how can i fetch data from this variable? I am talking if i use my own code?
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Of course. The parser doesn't care where the data comes from. It takes a string of xml data and a flag wether this is the last chunk of data or not.
You can pass the complete data in one go and set is_final to true.

Code: Select all

xml_parse($xml_parser, $data, true)
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

thanks man let my try this, one last thing i wanted to know is:
Please see : http://208.109.22.111/ticketchest/nutest.php
you will see here an xml response.
when i call following code i get this xml

Code: Select all

echo '' . htmlspecialchars($soapclient->response, ENT_QUOTES) . ''
now i wanted to parse this xml but it don't get parse as you will see there is few extra things at the start of it. how can i solve this issue. 2ndly in my file i was getting 4096 data every time in this case if my data is too much how can i Handel this issue.

thanks for the help
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Hm, why do you need to parse the "plain" xml from the soap response? It doesn't make much sense to use a soap extension/class if you have to do it all manually by your self anyway.

e.g.

Code: Select all

<?php
$c = new SoapClient('http://www.webservicex.net/geoipservice.asmx?WSDL');
$params = array('IPAddress'=>'88.72.14.195');
$r = $c->__call('GetGeoIP', array($params));
$georesult = $r->GetGeoIPResult;
echo "<pre>\n";
echo $georesult->IP, "\n";
echo $georesult->CountryName, "\n";
echo "</pre>\n";
?>

Image
Maybe a moderator can split this new topic?
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

volka wrote:Hm, why do you need to parse the "plain" xml from the soap response? It doesn't make much sense to use a soap extension/class if you have to do it all manually by your self anyway.
e.g.

Code: Select all

<?php
$c = new SoapClient('http://www.webservicex.net/geoipservice.asmx?WSDL');
$params = array('IPAddress'=>'88.72.14.195');
$r = $c->__call('GetGeoIP', array($params));
$georesult = $r->GetGeoIPResult;
echo "<pre>\n";
echo $georesult->IP, "\n";
echo $georesult->CountryName, "\n";
echo "</pre>\n";
?>
Image
Maybe a moderator can split this new topic?
every thing with the code you mentioned is fine except

Code: Select all

$georesult = $r->GetGeoIPResult;  //How you come to know about this method?
echo "<pre>\n";
echo $georesult->IP, "\n"; //How you come to know about this method?
echo $georesult->CountryName, "\n"; //How you come to know about this method?
In my case how i will come to know about these functions etc and if response values is more than one how i will fetch them?

thanks again
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

In this case not methods but properties.
I read the wsdl file (only because it's not that complex ;))
But php5's soap extension can return the list of functions and types it recognizes from a service description.

Code: Select all

<?php
$c = new SoapClient('http://www.webservicex.net/geoipservice.asmx?WSDL');
echo "<pre>\nfunctions:";
print_r($c->__getFunctions());
echo "</pre>\n";
echo "<pre>\nTypes:";
print_r($c->__getTypes());
echo "</pre>\n";
?>
<pre>
functions:Array
(
[0] => GetGeoIPContextResponse GetGeoIPContext(GetGeoIPContext $parameters)
[1] => GetGeoIPResponse GetGeoIP(GetGeoIP $parameters)
[2] => GeoIP GetGeoIPContext()
[3] => GeoIP GetGeoIP(string $IPAddress)
[4] => GeoIP GetGeoIPContext()
[5] => GeoIP GetGeoIP(string $IPAddress)
)
</pre>
<pre>
Types:Array
(
[0] => struct GetGeoIPContext {
}
[1] => struct GetGeoIPContextResponse {
GeoIP GetGeoIPContextResult;
}
[2] => struct GeoIP {
int ReturnCode;
string IP;
string ReturnCodeDetails;
string CountryName;
string CountryCode;
}
[3] => struct GetGeoIP {
string IPAddress;
}
[4] => struct GetGeoIPResponse {
GeoIP GetGeoIPResult;
}
)
</pre>
nusoap probably provides similar functionality.
kevin7654
Forum Newbie
Posts: 19
Joined: Sat Feb 18, 2006 2:38 pm

Post by kevin7654 »

Thanks so much for the responses. Here's the code I am going to try to use:

Code: Select all

$data = file_get_contents('php://input'); 

$xml = simplexml_load_string($data);
foreach($xml->Shipment as $shipment) {
        $body = $body . '<pre>';
        $body = $body . ' packageId: ', $shipment['PackageID'], "\n",
                ' Status: ', $shipment['Status'], "\n",
                ' ShipDate: ', $shipment['ShipDate'], "\n",
                ' TrackingNumber: ', $shipment['TrackingNumber'], "\n";
        foreach($shipment->Item as $item) {
                $body = $body . '  ItemId: ', $item['ItemID'], "\n";
        }
        $body = $body . "</pre>\n";
}
Unfortunately I don't have much of a way to test it besides just waiting for them to post something. Thanks again for your help.

Kevin
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

Code: Select all

$xml = simplexml_load_string($data);
foreach($xml->Shipment as $shipment) {
        $body = $body . '<pre>';
        $body = $body . ' packageId: ', $shipment['PackageID'], "\n",
                ' Status: ', $shipment['Status'], "\n",
                ' ShipDate: ', $shipment['ShipDate'], "\n",
                ' TrackingNumber: ', $shipment['TrackingNumber'], "\n";
        foreach($shipment->Item as $item) {
                $body = $body . '  ItemId: ', $item['ItemID'], "\n";
        }
Using above code i want to parse data given below given xml output, I tried but it did not worked please help me.
or Please see : http://208.109.22.111/ticketchest/nutest.php you will see the response in xml formate and debug output where there is an array with the data, please help me if i can parse it.

Code: Select all

HTTP/1.1 200 OK Connection: keep-alive Date: Tue, 31 Oct 2006 05:15:07 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 1.1.4322 Cache-Control: private, max-age=0 Content-Type: text/xml; charset=utf-8 Content-Length: 1193 <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetVenueListResponse xmlns="http://www.eventinventory.com/webservices/"><GetVenueListResult><ROOT xmlns=""><METHODINFO><channelName>Basic View</channelName><methodName>GetVenueList</methodName><parameters>APPCLIENT_ID=2220&EVENT_ID=6&STARTDATE=&INCDAYS=</parameters><processTime type="milliseconds">5.0200</processTime></METHODINFO><DATA xmlns:sql="urn:schemas-microsoft-com:xml-sql"><row THISID="1987" THISNAME="Alliance Theatre" ST="GA" /><row THISID="238" THISNAME="Broward Center Amaturo" ST="FL" /><row THISID="536" THISNAME="Fabulous Fox Theatre - St. Louis" ST="MO" /><row THISID="2233" THISNAME="Ford's Theatre" ST="DC" /><row THISID="657" THISNAME="Goodman Theatre - Albert" ST="IL" /><row THISID="945" THISNAME="Lowell Memorial Auditorium" ST="MA" /><row THISID="1598" THISNAME="Stage Theatre" ST="CO" /><row THISID="2963" THISNAME="Walnut Street Theatre" ST="PA" /></DATA></ROOT></GetVenueListResult></GetVenueListResponse></soap:Body></soap:Envelope>
User avatar
itsmani1
Forum Regular
Posts: 791
Joined: Mon Sep 29, 2003 2:26 am
Location: Islamabad Pakistan
Contact:

Post by itsmani1 »

hay hay hay

i been able to solve the issue till some extent

by using following method i am able get exact xml output;

Code: Select all

echo '<pre>' . htmlspecialchars($soapclient->responseData, ENT_QUOTES) . '</pre>';
final problem is i am using php 4.x.x and it don't support

Code: Select all

simplexml_load_string()
what could be the solution for it
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

volka wrote:Hm, why do you need to parse the "plain" xml from the soap response? It doesn't make much sense to use a soap extension/class if you have to do it all manually by your self anyway.
Post Reply