You are here:  » nesting parse call inside callback function


nesting parse call inside callback function

Submitted by Johnny N on Wed, 2009-04-08 11:18 in

Am I able to nest the MagicParse_parse call inside the callback function?

if not how do I accomplish something similar?

I am parsing an xml file (see details on this forum post http://www.magicparser.com/node/857) and converting to csv.

but I want to add to each row of the csv file, and the data I want to add comes from a different xml file.
so I was thinking that I could make the call again within the callback function, but this does not seem to work.

the new xml feed requires the hotelId in the url, (which I get from first xml file)

I also noticed that I cannot return an array from the callback function (using globals instead)

here is the returned xml code from the url

<?xml version="1.0" encoding="ISO-8859-1"?>
<HtSearchRq>
<Success>True</Success>
<LangID>EN</LangID>
<Destination>Golden Sands - Albena</Destination>
<HID>4274</HID>
<Hotel Name=".Com Albena">
<_Rating>3+</_Rating>
<Official_Rating>3+ stars</Official_Rating>
<Board_Type></Board_Type>
<Hotel_Desc><![CDATA[.Com Albena is the first and only hotel of this kind in Albena.It is an AI completely youth oriented destination well known for its facilities and high standard servises..Com is definitely going to surprise you with the specially organized nights,its own night club,swimming pool,water sports and the within walking distance Ralitsa Superior which is is a four-star boutique Spa (Jacuzzi, special rooms for thermo-therapy, sauna and steam bath etc).You will actually experience a truly unforgettable vacation always within sophistication and attentive accommodation.Hotel’s distance from Varna Airport is 40 km.]]></Hotel_Desc>
<Hotel_Photos>
<Photo>http://images.mydomain.com/photos/4274/xml.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Pool_Night.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Main.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Room.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Buffet.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Entrance.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Pool.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Pool_and_Moon.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Outside.jpg</Photo>
<Photo>http://images.mydomain.com/photos/4274/Entrance_Night.jpg</Photo>
</Hotel_Photos>
<Hotel_Facilities>
<Facility>Animation</Facility>
<Facility>Beach Volley</Facility>
<Facility>Disco</Facility>
<Facility>Football field(s)</Facility>
<Facility>Gym</Facility>
<Facility>Hairdresser</Facility>
<Facility>Jacuzzi</Facility>
<Facility>Lobby Bar</Facility>
<Facility>Restaurant(s)</Facility>
<Facility>Snack Bar</Facility>
<Facility>SPA</Facility>
<Facility>Swimming Pool Indoor</Facility>
<Facility>Tennis Court(s)</Facility>
<Facility>Water Sports</Facility>
<Facility>Wi Fi Internet Connection</Facility>
</Hotel_Facilities>
<Room_Types>
<Room name='Twin Double for Single Use (A )'>
<Facility>Air Conditioning</Facility>
<Facility>Bathroom with bathtub or Shower</Facility>
<Facility>Hair Dryer</Facility>
<Facility>Terrace Balcony</Facility>
<Facility>Towels</Facility>
<Facility>TV</Facility>
</Room>
<Room name='Twin Double Room (A )'>
<Facility>Air Conditioning</Facility>
<Facility>Bathroom with bathtub or Shower</Facility>
<Facility>Hair Dryer</Facility>
<Facility>Terrace Balcony</Facility>
<Facility>Towels</Facility>
<Facility>TV</Facility>
</Room>
</Room_Types>
<AI_Type>CLASSIC</AI_Type>
<AI_Desc><![CDATA[MEALSBreakfast(7.30. – 10.00)
Continental and English breakfast offers you great variety of sausages, cheese, fresh fruits, desserts, hot muffins, pancakes, croissantsLate breakfast: (10.00. – 11.00)Lunch(12.30. – 14.30)Dinner(18.30. – 21.30)International cuisine offers a variety of fresh salads and dishes, special children menu, vegetarian buffet with variety of low-calorie dishes, fruits, ice cream and etc.
Theme nights: Bulgarian traditional, Italian, Fish foodLate dinner(00.00 - 02.00)at .Com restaurantSnacksSnack Bar .Com 11.00 - 16.30,Snacks, salads, pizza, pasta, barbeque, pomes frites, hot drinks, desserts, pastries, fruits.
Ice –creams offered from 11.00 till 21.30
At restaurant .Com - children’s buffet.Snacks on the beach at the Havana bar 11.00- 16.30,Snacks, pizza, salads, barbecue, draft beer, fruits, soft drinks and coffee
 ]]></AI_Desc>
<AI_Facilities>
</AI_Facilities>
<Erratas><![CDATA[]]></Erratas>
</Hotel>
</HtSearchRq>

here is what i was trying to do with my code

<?php
error_reporting(E_ALL ^ E_NOTICE);
  header("Content-Type: text/plain;");
  // uncomment next 2 lines to force download rather than display within browser
  // header("Content-Type: application/octet-stream");
  // header("Content-Disposition: attachment; filename=hotels.csv");
  require("MagicParser.php");
print "Country name, country ID, country code, destination name, destination ID, resort name, resort ID, hotel name, hotel ID, hotel latitude, hotel longitude, image url, link, rating, description\n";
  function myHotelHandler($hotelRecord){
global $hotelDetail;
$hotelDetail = array();
foreach($hotelRecord as $k => $v)
{
if ( strpos($k,"OFFICIAL")!==FALSE) $hotelDetail["rating"] = $v;
elseif (strpos($k,"DESC")!==FALSE) $hotelDetail["description"] = $v;
}
//return $hotelDetail;
  }
  function myRecordHandler($record)
  {
    // countryname, countryId, countryCode, destinationName, destinationId, resortId, resortName, hotelId, hotelName, hotelLat, hotelLong
    $countryName = $record["COUNTRY-NAME"];
    $countryId = $record["COUNTRY-ID"];
    $countryCode = $record["COUNTRY-CODE"];
    foreach($record as $k => $v)
    {
      $v = str_replace(",","",$v);
      if (strpos($k,"HOTEL")!==FALSE && strpos($k,"NAME")!==FALSE) $hotelName = $v;
      elseif (strpos($k,"HOTEL")!==FALSE && strpos($k,"ID")!==FALSE) $hotelId = $v;
      elseif (strpos($k,"HOTEL")!==FALSE && strpos($k,"LATITUDE")!==FALSE) $hotelLat = $v;
      elseif (strpos($k,"HOTEL")!==FALSE && strpos($k,"LONGITUDE")!==FALSE) $hotelLong = $v;
      elseif (strpos($k,"RESORT")!==FALSE && strpos($k,"NAME")!==FALSE) $resortName = $v;
      elseif (strpos($k,"RESORT")!==FALSE && strpos($k,"ID")!==FALSE) $resortId = $v;
      elseif (strpos($k,"DESTINATION")!==FALSE && strpos($k,"ID")!==FALSE) $destinationId = $v;
      elseif (strpos($k,"DESTINATION")!==FALSE && strpos($k,"NAME")!==FALSE) $destinationName = $v;
      if ($hotelId && $hotelName && $hotelLat && $hotelLong)
      {
// real world example below, testing example below that.
// MagicParser_parse("http://xml.mydomain.com/webservices//get_hoteldetails.asp?LangID=EN&HID=".$hotelId."&Username=xmltestme&Password=xxxxxx", "myHotelHandler", "xml|HtSearchRq/");
    MagicParser_parse("hoteldetail.xml", "myHotelHandler", "xml|HtSearchRq/");
     print $countryName.","
             .$countryId.","
             .$countryCode.","
             .$destinationName.","
             .$destinationId.","
             .$resortName.","
             .$resortId.","
             .$hotelName.","
             .$hotelId.","
             .$hotelLat.","
             .$hotelLong.","
."http://www.mydomain.com/photos/".$hotelId."/Main.jpg,"
."http://www.mydomain.com/".$countryId."/".str_replace(" ", "-", $countryName)."/".$destinationId."/".str_replace(" ", "-", $destinationName)."/".$resortId."/".str_replace(" ", "-", $resortName)."/".str_replace(" ", "-", $hotelName)."/,"
.$hotelDetail["rating"].","
."\"".$hotelDetail["description"]."\"\n";
        $hotelId = "";$hotelName = "";$hotelLat = "";$hotelLong = "";
      }
    }
  }
MagicParser_parse("hotellistsmall.xml","myRecordHandler","xml|HTSEARCHRQ/COUNTRY/");
?>

unfortunately I get nothing back.

I can get info back if I only call my hoteldetail.xml file using the following code

<?php
error_reporting(E_ALL ^ E_NOTICE);
$hotelId=3;
  header("Content-Type: text/plain;");
  // uncomment next 2 lines to force download rather than display within browser
  // header("Content-Type: application/octet-stream");
  // header("Content-Disposition: attachment; filename=hotels.csv");
  require("MagicParser.php");
// print "Country name, country ID, country code, destination name, destination ID, resort name, resort ID, hotel name, hotel ID, hotel latitude, hotel longitude, image url, link\n";
  function myHotelHandler($hotelRecord){
global $hotelDetail ;
$hotelDetail = array();
foreach($hotelRecord as $k => $v)
{
if ( strpos($k,"OFFICIAL")!==FALSE) $hotelDetail["rating"] = $v;
elseif (strpos($k,"DESC")!==FALSE) $hotelDetail["description"] = $v;
// elseif (strpos($k, "DESTINATION")!=FALSE) $hotelDetail["destination"] = $v;
}
// print_r($hotelDetail);
// return $hotelDetail;
}
$hotelDetail2 = MagicParser_parse("hoteldetail.xml", "myHotelHandler", "xml|HTSEARCHRQ/HOTEL/");
print_r($hotelDetail);
?>

Submitted by support on Wed, 2009-04-08 11:50

Hello Johnny,

As Magic Parser contains its own global variables to keep track of the parse process i'm afraid it cannot be called again whilst in the middle of a current parse.

What I would suggest in this situation would be to:

1) Create the CSV from the hotel list XML as before; the only difference being create the complete header row including fields that you will subsequently get from the hotel info XML.

2) Read the CSV line by line; and for each line extract the hotel ID and then request and parse the hotel info XML for that hotel

3) Output the existing line, followed by the new information from the hotel info XML

Here's a full example based on the XML to CSV code I posted yesterday. This will require a writable temporary directory in order to create the intial CSV - for example "data" in the same directory as the script. The easiest way to make a directory writable by PHP is to use your FTP program - right click on the folder in the destination window and look for "Permissions..." or maybe "Properties..." and then Permissions. Then give write access to all users - owner, group and world.

<?php
  header
("Content-Type: text/plain;");
  require(
"MagicParser.php");
  
$tempFile "data/hotelsTemp.csv";
  
$tempFileP fopen($tempFile,"w");
  if (!
$tempFileP) die("Could not create ".$tempFile);
  
fputs($tempFileP,"Country name, country ID, country code, destination name, destination ID, resort name, resort ID, hotel name, hotel ID, hotel latitude, hotel longitude, image url, link, rating, description\n");
  function 
myRecordHandler($record)
  {
    
$countryName $record["COUNTRY-NAME"];
    
$countryId $record["COUNTRY-ID"];
    
$countryCode $record["COUNTRY-CODE"];
    foreach(
$record as $k => $v)
    {
      
$v str_replace(",","",$v);
      if (
strpos($k,"HOTEL")!==FALSE && strpos($k,"NAME")!==FALSE$hotelName $v;
      elseif (
strpos($k,"HOTEL")!==FALSE && strpos($k,"ID")!==FALSE$hotelId $v;
      elseif (
strpos($k,"HOTEL")!==FALSE && strpos($k,"LATITUDE")!==FALSE$hotelLat $v;
      elseif (
strpos($k,"HOTEL")!==FALSE && strpos($k,"LONGITUDE")!==FALSE$hotelLong $v;
      elseif (
strpos($k,"RESORT")!==FALSE && strpos($k,"NAME")!==FALSE$resortName $v;
      elseif (
strpos($k,"RESORT")!==FALSE && strpos($k,"ID")!==FALSE$resortId $v;
      elseif (
strpos($k,"DESTINATION")!==FALSE && strpos($k,"NAME")!==FALSE$destinationName $v;
      elseif (
strpos($k,"DESTINATION")!==FALSE && strpos($k,"ID")!==FALSE$destinationId $v;
      if (
$hotelId && $hotelName && $hotelLat && $hotelLong)
      {
        
fputs($tempFileP,$countryName.","
             
.$countryId.","
             
.$countryCode.","
             
.$destinationName.","
             
.$destinationId.","
             
.$resortName.","
             
.$resortId.","
             
.$hotelId.","
             
.$hotelName.","
             
.$hotelLat.","
             
.$hotelLong."\n");
        
$hotelId "";$hotelName "";$hotelLat "";$hotelLong "";
      }
    }
  }
  
MagicParser_parse("hotellistsmall.xml","myRecordHandler","xml|HTSEARCHRQ/COUNTRY/");
  
fclose($tempFileP);
  function 
myHotelHandler($record)
  {
    global 
$line;
    global 
$fields;
    global 
$mainFileP;
    
// remove white space and newlines from end of existing line ready to append
    
$line trim($line);
    
$imageUrl "http://www.mydomain.com/photos/".$fields[8]."/Main.jpg"
    
$link "http://www.mydomain.com/".$fields[1]."/".str_replace(" ""-"$fields[0])."/".$fields[4]."/".str_replace(" ""-"$fields[3])."/".$fields[6]."/".str_replace(" ""-"$fields[5])."/".str_replace(" ""-"$fields[7])."/"
    
$rating $record["HOTEL/_RATING"];
    
$description str_replace(",","",$record["HOTEL/HOTEL_DESC"]);
    
// now create the full output line with the new fields
    
fputs($mainFileP,$line.",".$imageUrl.",".$link.",".$rating.",".$description."\n";
  }
  
// open the temp file again this time for reading
  
$tempFileP fopen($tempFile,"r");
  
// open the main file to contain the complete CSV for writing
  
$mainFile "data/hotels.csv";
  
$mainFileP fopen($mainFile,"w");
  if (!
$mainFileP) die("Could not create ".$mainFile);
  
// output the header line to the new file
  
$header fgets($tempFileP);
  
fwrite($mainFileP,$header);
  
// now read each row and add the line with call to hotel detail XML
  
do {
    
$line fgets($tempFileP);
    
$fields explode(",",$line);
    
$hotelId $fields[8];
    
MagicParser_parse("http://xml.mydomain.com/webservices//get_hoteldetails.asp?LangID=EN&HID=".$hotelId."&Username=xmltestme&Password=xxxxxx""myHotelHandler""xml|HTSEARCHRQ/");
  } while(!
feof($tempFileP));
  
fclose($fMainFileP);
  
// complete hotel database is now in data/hotels.csv
?>

Hope this points you in the right direction!

Cheers,
David.