You are here:  » looping through child object

Support Forum



looping through child object

Submitted by hoeksms on Fri, 2007-06-08 10:59 in

I need to import data into a multistore (osCommerce). The product records contain information about which shop the product should be published to. Here's a simplified example of the XML data:

<products>
<product>
<products_id>008642</products_id>
<products_name>product A</products_name>
<products_price>15.9244</products_price>
<shops>
<shop>
<shop_id>1</shop_id>
<product2shop_status_id>1</product2shop_status_id>
</shop>
<shop>
<shop_id>2</shop_id>
<product2shop_status_id>1</product2shop_status_id>
</shop>
<shop>
<shop_id>3</shop_id>
<product2shop_status_id>0</product2shop_status_id>
</shop>
</shops>
</product>
<product>
<products_id>008642</products_id>
<products_name>Product B</products_name>
<products_price>12.7465</products_price>
<shops>
<shop>
<shop_id>1</shop_id>
<product2shop_status_id>1</product2shop_status_id>
</shop>
<shop>
<shop_id>2</shop_id>
<product2shop_status_id>1</product2shop_status_id>
</shop>
<shop>
<shop_id>3</shop_id>
<product2shop_status_id>0</product2shop_status_id>
</shop>
</shops>
</product>
</products>

The current output looks like this:

008642
product A
15.9244
1(), 2(), 3(), 1(), 2(), 3(),

008642
Product B
12.7465

So this obviously does not work because the nested loop goes through all the records instead of just the active record.
My PHP code looks like this:

<?php
    
require("MagicParser.php");
    function 
myRecordHandler($product) {
        
$i 0;
        while(
1) {
            if (
$i$postfix "@".$i;
            if (!isset(
$product["PRODUCT".$postfix])) break;
            
$products_id $product["PRODUCT/PRODUCTS_ID".$postfix];
            
$products_name $product["PRODUCT/PRODUCTS_NAME".$postfix];
            
$products_price $product["PRODUCT/PRODUCTS_PRICE".$postfix];
            echo 
$products_id '<br>' ;
            echo 
$products_name '<br>' ;
            echo 
$products_price '<br>' ;
            
// get active shops
            
$y 0;
            while(
1) {
                if (
$y) {
                    
$postfx "@".$y;
                }
                if (!isset(
$product["PRODUCT/SHOPS/SHOP".$postfx])) {
                    break;
                }
                
$shop_id $product["PRODUCT/SHOPS/SHOP/SHOP_ID".$postfx];
                
$product2shop_status_id $product["PRODUCT/SHOPS/SHOP/PRODUCTS2SHOP_STATUS_ID".$postfx];
                echo 
$shop_id '(' $product2shop_status_id '), ' ;
                
$y++;
            }
            echo 
'<hr>' ;
            
$i++;
        }
    }
    
MagicParser_parse("example.xml","myRecordHandler","xml|PRODUCTS/");
?>

Submitted by support on Fri, 2007-06-08 11:14

Hi,

In order to process the style of XML that you are using here, where there are multiple product records; I would recommend using a lower level format string:

xml|PRODUCTS/PRODUCT/

This will call your record handler once for each product, meaning you only have to resolve out the individual SHOP records, which is more straight forward.

That aside, I think the only reason your original version wasn't working is because of a couple of typo's - you have used "postfx" instead of "postfix" in a couple of places, and then the key name used to access the $product2shop_status_id value is "SHOPS/SHOP/PRODUCTS2SHOP_STATUS_ID" instead of "SHOPS/SHOP/PRODUCT2SHOP_STATUS_ID" (note the incorrect "S" on the end of PRODUCT).

The way I would recommend working with this feed can be seen in the following example:

<?php
    
require("MagicParser.php");
    function 
myRecordHandler($product) {
        
$products_id $product["PRODUCTS_ID"];
        
$products_name $product["PRODUCTS_NAME"];
        
$products_price $product["PRODUCTS_PRICE"];
        echo 
$products_id '<br>' ;
        echo 
$products_name '<br>' ;
        echo 
$products_price '<br>' ;
        
$i 0;
        while(
1) {
            if (
$i$postfix "@".$i;
            if (!isset(
$product["SHOPS/SHOP".$postfix])) break;
            
$shop_id $product["SHOPS/SHOP/SHOP_ID".$postfix];
            
$product2shop_status_id $product["SHOPS/SHOP/PRODUCT2SHOP_STATUS_ID".$postfix];
            echo 
$shop_id '(' $product2shop_status_id '), ';
            
$i++;
        }
        echo 
'<hr>' ;
    }
    
MagicParser_parse("multistore.xml","myRecordHandler","xml|PRODUCTS/PRODUCT/");
?>

You can see the output, which I think is what you want here:

http://www.magicparser.com/examples/multistore.php

Don't forget to change multistore.xml to example.xml if that is what the file is called on your server!...

Hope this helps,
Cheers,
David.

Submitted by hoeksms on Fri, 2007-06-08 11:35

Thank you !!!

Submitted by crounauer on Fri, 2007-06-22 14:00

Hi David,

Would you please be able to tell me what i'm doing wrong here. The data should be in the format of Room ref, then the relevant dates. At the moment the relevant dates is sandwhiched in between the two room refs.

Looks like this...

Description: 2163 22/06/2007 00:00:00 23/06/2007 00:00:00 24/06/2007 00:00:00 25/06/2007 00:00:00 22/06/2007 00:00:00 23/06/2007 00:00:00 24/06/2007 00:00:00 25/06/2007 00:00:00 Description: 2164

Would like it to look like this...

Description: 2163 22/06/2007 00:00:00 23/06/2007 00:00:00 24/06/2007 00:00:00 25/06/2007 00:00:00
Description: 2164 22/06/2007 00:00:00 23/06/2007 00:00:00 24/06/2007 00:00:00 25/06/2007 00:00:00

Thanks,
Simon

<?php
function parse_hotel($hotel)
  {
$i1 0;
  while(
1) {
    if (
$i1$postfix1 "@".$i1;
      if (!isset(
$hotel["ROOM".$postfix1])) break;
      print 
$hotel["ROOM/REF".$postfix1]."&nbsp;";
$i 0;
  while(
1) {
    if (
$i$postfix "@".$i;
      if (!isset(
$hotel["ROOM/RATE".$postfix])) break;
        print 
$hotel["ROOM/RATE/DATE".$postfix]."&nbsp;";           
      
$i++;
    }
      
$i1++;
    }
  }
$url "http://xmlfeed.laterooms.com/index.aspx?aid=1453&rtype=3&hids=1119&sdate=2007-07-05&nights=7";
MagicParser_parse($url,"parse_hotel","xml|HOTEL_SEARCH/HOTEL/LR_RATES/HOTEL_ROOMS/");
?>

Submitted by support on Fri, 2007-06-22 15:06

Hi Simon,

To resolve the rooms individually, I think you need to be using a lower level format string. Instead of:

xml|HOTEL_SEARCH/HOTEL/LR_RATES/HOTEL_ROOMS/

...i've just tried it with:

xml|HOTEL_SEARCH/HOTEL/LR_RATES/HOTEL_ROOMS/ROOM/

This will call your record handler function once for each room. The only other change you will need to make is to remove ROOM/ from each of the expressions within the record handler as they will no longer be part of the array keys. Here's the source code I used to try this out:

<?php
  
require("MagicParser.php");
  function 
parse_hotel($hotel)
  {
    
$i1 0;
    while(
1)
    {
      if (
$i1$postfix1 "@".$i1;
      if (!isset(
$hotel["REF".$postfix1])) break;
      print 
$hotel["REF".$postfix1]."&nbsp;";
      
$i 0;
      while(
1)
      {
        if (
$i$postfix "@".$i;
        if (!isset(
$hotel["RATE".$postfix])) break;
        print 
$hotel["RATE/DATE".$postfix]."&nbsp;";
        
$i++;
      }
      
$i1++;
    }
    print 
"<br />";
  }
$url "http://xmlfeed.laterooms.com/index.aspx?aid=1453&rtype=3&hids=1119&sdate=2007-07-05&nights=7";
MagicParser_parse($url,"parse_hotel","xml|HOTEL_SEARCH/HOTEL/LR_RATES/HOTEL_ROOMS/ROOM/");
?>

Hope this helps!
Cheers,
David.

Submitted by crounauer on Mon, 2007-06-25 09:33

Hi David,

Thank you very much for you help once again. I see now what I was doing wrong!

Thanks,
Simon

Submitted by crounauer on Tue, 2007-12-11 12:42

Hello,

The above script causes and error when $postfix = 0. It does not cause the script to stop working but does throw an error when set.

To remedy change this line

if ($y) {
  $postfx = "@".$y;
}

to this
if ($y >= 1) {$postfix = "@".$y;
  } else {
  $postfix = "";
}

Thanks,
Simon