Re: XML Parsing

From: Date: Thu, 17 Jul 2003 17:59:27 +0000
Subject: Re: XML Parsing
References: 1  Groups: php.general 
Request: Send a blank email to php-general+get-155662@lists.php.net to get a copy of this message
On Thu, 2003-07-17 at 10:03, Doug La Farge wrote: > Hello, > > I'm new to PHP but have been coding in Perl for over six years. I've > had a steep learning curve in the last few days. My task has been to > use fsockopen to pull in an XML stream, parse that XML stream, and > package up that data into a complex, but usable data structure. We've > been able to accomplish this in Perl but now I'm attempting to port the > Perl code to PHP. The Perl code was written by Randal Schwartz (for me) > but he's not interested in helping me solve the PHP problems I'm > running into. I'm hoping to find someone on this list savvy in Perl > and PHP, and understands complex data structures (in perl the hash > refs/pointers go about four levels deep). I've included below the PHP > code with three functions in question. Below each function is the Perl > code I'm attempting to port. > > Here are some URL's that might help: > > http://shop.sprocketdata.com/test.php - url for the code below > (which > works if you copy paste) > ignore the feof error- i left out the fsockopen because I know that's > not where the problem is nor does this error effect the output. > > http://stage.holdit.com/cgi-bin/is/shipping.cgi - url for > equivalent > code in perl (ignore the drop-down) > > http://stage.holdit.com/cgi-bin/is/fetch.cgi - the data > structure I'm > trying to achieve in PHP > > http://stage.holdit.com/cgi-bin/is/is.cgi - the raw XML data > structure > - almost useless until parsed and probably useless to look at :-). > > You'll also notice at the bottom of the code I've included how the PHP > XML parsed the data. It's very similar to the fetch.cgi - maybe it's > different and thus causing the problem but I don't see it. > > <?php > > $state = array(); > global $state; > > // these two associatative arrays will hold the data structure (I hope > :-) > $quote = array(); > global $quote; > $quotes = array(); > global $quotes; > > //XML start element > function startElement(&$Parser, &$Elem, &$Attr) { > global $state; //this works > array_push ($state, $Elem); //this works > $states = join (' ',$state); //can't interpolate the list so must > join - works > if ($states = "SHIPMENT PACKAGE") { //we make it this far if( $states == "SHIPMENT PACKAGE" ) { ^^ > echo "$states\n"; //for testing should on print once! > // $package_id = $Attr->{id}; // how to write this in PHP? > } > //This conditional is never met - QUOTE gets popped off before it > returns > elseif ($states = "SHIPMENT PACKAGE QUOTE") { //why does perl see > QUOTE? elseif( $states == "SHIPMENT PACKAGE QUOTE" ){ ^^ > echo "$states\n"; // testing > // %quote = ( package_id => $package_id, id => $attr->{id} ); //Perl > // $quote = array ( package_id => $package_id, id => $attr->{id} ); > //PHP version of above line? > } > } > > /*Perl > start_h => [ sub { > my ($tagname, $attr) = @_; > push @state, $tagname; > if ("@state" eq "shipment package") { > print "@state<br>";#testing > $package_id = $attr->{id}; > } > elsif ("@state" eq "shipment package quote") { > %quote = ( package_id => $package_id, id => $attr->{id} ); > print "@state<br>";#testing > } > }, "tagname, attr"], > */ > > // XML data > //This function might work but I don't know yet as QUOTE never stays in > the $state stack > function characterData(&$Parser, &$Line) { > global $state; > $states = join (' ',$state); > if ($states = "SHIPPMENT ERROR") { if( $states == "SHIPMENT ERROR" ) { ^^ > $error = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE BOXID") { elseif( $states == "SHIPMENT PACKAGE QUOTE BOXID" ) { ^^ > $boxID = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE CARRIER NAME") { elseif( $states == "SHIPMENT PACKAGE QUOTE CARRIER NAME" ) { ^^ > $quote{carrier_name} = $Line; // Doubting this will work - need to > fix this too > } > elseif ($states = "SHIPMENT PACKAGE QUOTE CARRIER CODE") { elseif( $states == "SHIPMENT PACKAGE QUOTE CARRIER CODE" ) { ^^ > $quote{carrier_code} = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE CLASS NAME") { elseif( $states == "SHIPMENT PACKAGE QUOTE CLASS NAME" ) { ^^ > $quote{class_name} = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE CLASS CODE") { elseif( $states == "SHIPMENT PACKAGE QUOTE CLASS CODE" ) { ^^ > $quote{class_code} = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE SERVICE NAME") { elseif( $states == "SHIPMENT PACKAGE QUOTE SERVICE NAME" ) { ^^ > $quote{service_name} = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE SERVICE CODE") { elseif( $states == "SHIPMENT PACKAGE QUOTE SERVICE CODE" ) { ^^ > $quote{service_code} = $Line; > } > elseif ($states = "SHIPMENT PACKAGE QUOTE RATE AMOUNT") { elseif( $states == "SHIPMENT PACKAGE QUOTE RATE AMOUNT" ) { ^^ > $quote{amount} = $Line; > } > } > > /* Perl > text_h => [ sub { > my ($text) = @_; > if ("@state" eq "shipment error") { > $error = $text; > } > elsif ("@state" eq "shipment package boxID") { > $boxID = $text; > } > elsif ("@state" eq "shipment package quote carrier name") { > $quote{carrier_name} = $text; > } > elsif ("@state" eq "shipment package quote carrier code") { > $quote{carrier_code} = $text; > } > elsif ("@state" eq "shipment package quote class name") { > $quote{class_name} = $text; > } > elsif ("@state" eq "shipment package quote class code") { > $quote{class_code} = $text; > } > elsif ("@state" eq "shipment package quote service name") { > $quote{service_name} = $text; > } > elsif ("@state" eq "shipment package quote service code") { > $quote{service_code} = $text; > } > elsif ("@state" eq "shipment package quote rate amount") { > $quote{amount} = $text; > } > }, "dtext"], > */ > > > function endElement(&$Parser, &$Elem) { > global $state; > $states = join (' ',$state); > if ($states = "SHIPMENT PACKAGE QUOTE") { if( $states == "SHIPMENT PACKAGE QUOTE" ) { ^^ > //echo "got QUOTE here $states\n"; > > /* > The following three lines need porting to PHP > there is much perl magic here - I can explain if it doesn't > make sense. The short of this is it's a rather complex structure > Perhaps this is where things are breaking? > */ > //$key = "@quote{qw(carrier_code service_code)}"; > //delete @quote{qw(id package_id)}; # artificial > //$quotes{$boxID}{$key} = {%quote}; > } > // obviously the part that pulls QUOTE off the $state stack > // perhaps a conditional? > array_pop($state); > } > > /*Perl > end_h => [ sub { > my ($tagname) = @_; > if ("@state" eq "shipment package quote") { > my $key = "@quote{qw(carrier_code service_code)}"; > delete @quote{qw(id package_id)}; # artificial > $quotes{$boxID}{$key} = {%quote}; > } > pop @state; > }, "tagname"], > */ > > > > //This code should work just fine > echo '<html><body><pre><form>'; > $xml_parser = xml_parser_create(); > xml_set_element_handler($xml_parser, "startElement", "endElement"); > xml_set_character_data_handler($xml_parser, "characterData"); > > //The XML data as returned from the server in it's raw form > $data = '<?xml version="1.0"?><shipment > > xsi:schemaLocation="http://www.intershipper.com/Interface/Intershipper/ > XML/v2.0/schemas response.xsd" > xmlns:xsi="http://www.w3.org/2001/XMLSchema- > instance"><version>2.0.0.0</version><shipmentID>1234</ > shipmentID><queryID>23456</queryID><deliveryType>COM</ > deliveryType><shipMethod>DRP</shipMethod><origination><name>John > Smith</name><address1>465 Tyende > Ovi</address1><address2></address2><address3></ > > address3>address3><city>Flagstaff</city><state>AZ</state><postal>86001</ > > postal>postal><country>US</country></origination><destination><name>Jane > Doe</name><address1>466 Tyende > Ovi</address1><address2></address2><address3></ > > address3>address3><city>Flagstaff</city><state>AZ</state><postal>86001</ > postal><country>US</country></destination><package > id="1"><boxID>1</boxID><weight > unit="LB">10.0</weight><dimensions > > unit="IN"><length>10.0</length><width>10.0</width><height>10.0</ > > height></dimensions><packaging>BOX</packaging><contents>OTR</ > contents><cod>18500</cod><insurance>15000</ > insurance><options><specialHandling > id="1"><code>SDD</code><name>Saturday > Delivery</name></specialHandling></options><quote > id="1"><carrier><code>UPS</code><name>United Parcel > > Service</name><account>123456789</account><invoiced>1</invoiced></ > carrier><class><code>1DY</code><name>1st > Day</name></class><service><code>NDA</code><name>Next Day > > Air</name></service><rate><amount>4201</amount><currency>USD</ > > currency></rate></quote><quote > id="2"><carrier><code>UPS</code><name>United Parcel > > Service</name><account>123456789</account><invoiced>1</invoiced></ > carrier><class><code>1DY</code><name>1st > Day</name></class><service><code>NDS</code><name>Next Day > Air > > Saver</name></service><rate><amount>3898</amount><currency>USD</ > > currency></rate></quote><quote > id="3"><carrier><code>UPS</code><name>United Parcel > > Service</name><account>123456789</account><invoiced>1</invoiced></ > carrier><class><code>1DY</code><name>1st > Day</name></class><service><code>NDM</code><name>Next Day > Air > > AM</name></service><rate><amount>7087</amount><currency>USD</ > > currency></rate></quote></package></shipment>'; > > if (!xml_parse($xml_parser, $data, feof($fp))) { > die(sprintf("XML error: %s at line %d", > xml_error_string(xml_get_error_code($xml_parser)), > xml_get_current_line_number($xml_parser))); > } > xml_parser_free($xml_parser); > echo '</select></form>'; > > > /* > Here is an example of the data returned from the XML parser > > SHIPMENT: > VERSION: 2.0.0.0 > SHIPMENTID: 1234 > QUERYID: 23456 > DELIVERYTYPE: COM > SHIPMETHOD: DRP > ORIGINATION: > NAME: John Smith > ADDRESS1: 465 Tyende Ovi > ADDRESS2: > ADDRESS3: > CITY: Flagstaff > STATE: AZ > POSTAL: 86001 > COUNTRY: US > DESTINATION: > NAME: Jane Doe > ADDRESS1: 466 Tyende Ovi > ADDRESS2: > ADDRESS3: > CITY: Flagstaff > STATE: AZ > POSTAL: 86001 > COUNTRY: US > PACKAGE: > BOXID: 1 > WEIGHT: 10.0 > DIMENSIONS: > LENGTH: 10.0 > WIDTH: 10.0 > HEIGHT: 10.0 > PACKAGING: BOX > CONTENTS: OTR > COD: 18500 > INSURANCE: 15000 > OPTIONS: > SPECIALHANDLING: > CODE: SDD > NAME: Saturday Delivery > QUOTE: > CARRIER: > CODE: UPS > NAME: United Parcel Service > ACCOUNT: 123456789 > INVOICED: 1 > CLASS: > CODE: 1DY > NAME: 1st Day > SERVICE: > CODE: NDA > NAME: Next Day Air > RATE: > AMOUNT: 4201 > CURRENCY: USD > QUOTE: > CARRIER: > CODE: UPS > NAME: United Parcel Service > ACCOUNT: 123456789 > INVOICED: 1 > CLASS: > CODE: 1DY > NAME: 1st Day > SERVICE: > CODE: NDS > NAME: Next Day Air Saver > RATE: > AMOUNT: 3898 > CURRENCY: USD > QUOTE: > CARRIER: > CODE: UPS > NAME: United Parcel Service > ACCOUNT: 123456789 > INVOICED: 1 > CLASS: > CODE: 1DY > NAME: 1st Day > SERVICE: > CODE: NDM > NAME: Next Day Air AM > RATE: > AMOUNT: 7087 > CURRENCY: USD > */ > ?> > > > I do apologize for the length of this email. I did my best to make it > short. -- Tyler Lane <tlane@lyrical.net>

Attachment: [application/pgp-signature] This is a digitally signed message part signature.asc
« previous php.general (#155662) next »