1

I am trying to get information out of an XML file and I can´t get it to work. Here is my code:

$xml = simplexml_load_file('http://www.website.de/file.xml');

$query  = "SELECT * FROM table WHERE shop='name' and datum='' LIMIT 5";          
$result = mysql_query($query) or die("Error: " . mysql_error());  
$db_erg = mysql_query( $query);
while ( $inhalt = mysql_fetch_array( $db_erg, MYSQL_ASSOC))
{
    $i = $inhalt['name'];
    $name = $xml->record[$i]->PRODUCT_NAME;
    $link = $xml->record[$i]->PRODUCT_LINK;
    $preis = $xml->record[$i]->PRICE;
    $versand = $xml->record[$i]->SHIPPING_COST;
    $ean = $xml->record[$i]->PRODUCT_CODE;
    $bild = $xml->record[$i]->PRODUCT_IMAGE_URL;
    $datum = time();
    $id = $inhalt['id'];
    echo "<p>".$id." geaendert.</p>";
}

Every time I run the script it gives me the error...

Trying to get property of non-object in...

...in the lines from $name to $bild. So I guess it has something to do with the $i but I don't really understand why this doesn't work. I would appreciate some help.

P.S: I know that this is not a safe way to use MySQL. The script on the finished site will only use mysqli prepared statements.

Here is the XML file I am manipulating:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<csv_data_records source="/var/www/network/domains/webservice/public_html/partner/functions/../../../../../tmp/productdata_cf45f01cb623aa26d26b25d362e11b56.tmp" datetime="2014-10-29T19:31:38+01:00" >
   <record>
      <PRODUCT_ID>9868.1</PRODUCT_ID>
      <PRODUCT_CODE>4032314007020</PRODUCT_CODE>
      <PRODUCT_CODE_TYPE>EAN</PRODUCT_CODE_TYPE>
      <PRODUCT_NAME>Luposan Kräuterkraft 30 Pulver - 1000 g</PRODUCT_NAME>
      <BRAND>Luposan</BRAND>
      <PRICE>22.99</PRICE>
      <PRICE_OLD>26.99</PRICE_OLD>
      <PRICE_CURRENCY>EUR</PRICE_CURRENCY>
      <CATEGORY>Hund &gt; Spezialfutter &amp; Nahrungsergänzungen &gt; Haut &amp; Fell &gt; Luposan</CATEGORY>
      <PRODUCT_IMAGE_URL>http://marketing.net.zooplus.de/ts/i3101179/tsv?tst=!!!TIME_STAMP!!!&amp;amc=aff.zooplus.20478.24084.8290&amp;rmd=1&amp;trg=http%3A%2F%2Fmedia.zooplus.com%2Fbilder%2F1%2F400%2F9868_luposan_kraeuterkraftb_1.jpg</PRODUCT_IMAGE_URL>
      <PRODUCT_LINK>http://marketing.net.zooplus.de/ts/i3101179/tsc?tst=!!!TIME_STAMP!!!&amp;amc=aff.zooplus.20478.24084.8290&amp;rmd=1&amp;trg=http%3A%2F%2Fwww.zooplus.de%2F-306243%2Fshop%2F%252B10PRFDEAFF%2Fhunde%2Fhundefutter_ergaenzung%2Fhaut_haare%2Fluposan%2F9868</PRODUCT_LINK>
      <AVAILABILITY>in stock</AVAILABILITY>
      <SHIPPING_COST>0.00</SHIPPING_COST>
      <PRODUCT_UNIT_PRICE>22.99</PRODUCT_UNIT_PRICE>
      <PRODUCT_UNIT_MEASURE>1</PRODUCT_UNIT_MEASURE>
      <PRODUCT_UNIT_BASE_VALUE>kg</PRODUCT_UNIT_BASE_VALUE>
 </record>
w5m
  • 2,286
  • 3
  • 34
  • 46
Dennis
  • 595
  • 1
  • 6
  • 22
  • `$xml` isn't defined ANYWHERE in your code. So yeah, exactly as PHP is saying. you're trying to access a property of a non-object (e.g. an undefined variable has no properties). – Marc B Oct 29 '14 at 20:46
  • @marc I know, i forgot to show this here on the site. But it is in my script. I added it now to the code above. Sorry. – Dennis Oct 29 '14 at 20:47
  • @Dennis we can't provide any help if we don't know the structure of the XML in your file, or what `$inhalt['name']` is. Print the value of `$inhalt['name']` to check it's what you think it is, and add that and a snippet of the XML file to your question. – i alarmed alien Oct 29 '14 at 20:48
  • then do a `var_dump($xml)` and see if you've actually got `record[whatever]` elements available. – Marc B Oct 29 '14 at 20:48
  • @ialarmedalien I added the structure of the xml file. – Dennis Oct 29 '14 at 20:54
  • @MarcB I did the var_dump and there it shows all the informations from the xml file. – Dennis Oct 29 '14 at 20:55
  • @ialarmedalien The value of $inhalt['name'] is the number of each entry in this xml file. Since the code of the part of the xml file above is the first entry the value of $inhalt['name'] is 0. – Dennis Oct 29 '14 at 21:01
  • Are you sure that your xml file is loading correctly? – i alarmed alien Oct 29 '14 at 21:08
  • @ialarmedalien Yes it does. There is no problem. – Dennis Oct 29 '14 at 21:09
  • @ialarmedalien If i change the script from $i = $inhalt['name']; to $i = 0; everything works fine. But since i know for sure that the value of $inhalt['name'] is 0 i don´t understand the whole problem. – Dennis Oct 29 '14 at 21:09
  • Can you `print_r($inhalt)`? – i alarmed alien Oct 29 '14 at 21:20

1 Answers1

2

The code that you have posted works correctly for me, so I would imagine that the issue is that the XML file is not loading or that your $i is out of the range for the values in the XML file. Both can be guarded against with checks added to your code:

$xml = simpleXML_load_file($url, "SimpleXMLElement"); 
if ($xml === false) 
{ 
   die("Could not load the XML file!"); 
} 

$i = $inhalt['name'];
if (isset ($xml->record[$i])) {
    // do your processing
}
else {
    // trigger an error / warning
}

If you are gathering data for a large number of products, you may find it more efficient to store it in an array, indexed by the element name. It does at least save you from having to write a load of similar statements.

You could also use simpleXML's XPath implementation to find the relevant record in your XML file by matching the PRODUCT_ID with the ID stored in your database. Here is an example:

$data = array();
$prod_id = $inhalt['artikelnummer'];

# this finds the record nodes where the value of PRODUCT_ID is $prod_id
# [.='$prod_id'] means the node's text content should match $prod_id
# the /.. at the end of the query returns the parent node, i.e. the record
foreach ($xml->xpath("record/PRODUCT_ID[.='$prod_id']/..") as $e) {
    foreach( array('PRODUCT_NAME', 'PRODUCT_LINK', 'PRICE', 'SHIPPING_COST',
        'PRODUCT_CODE', 'PRODUCT_IMAGE_URL') as $x ) {
        # make sure that the relevant value element is there!
        if (isset($e->$x)) {
            $data[$x] = (string)$e->$x;
        }
    }
    print_r($data);
    // do whatever you want with $data
}

Output:

Array
(
    [PRODUCT_NAME] => Luposan Kräuterkraft 30 Pulver - 1000 g
    [PRODUCT_LINK] => http://marketing.net.zooplus.de/ts/i3101179/tsc?tst=!!!TIME_STAMP!!!&amc=aff.zooplus.20478.24084.8290&rmd=1&trg=http%3A%2F%2Fwww.zooplus.de%2F-306243%2Fshop%2F%252B10PRFDEAFF%2Fhunde%2Fhundefutter_ergaenzung%2Fhaut_haare%2Fluposan%2F9868
    [PRICE] => 22.99
    [SHIPPING_COST] => 0.00
    [PRODUCT_CODE] => 4032314007020
    [PRODUCT_IMAGE_URL] => http://marketing.net.zooplus.de/ts/i3101179/tsv?tst=!!!TIME_STAMP!!!&amc=aff.zooplus.20478.24084.8290&rmd=1&trg=http%3A%2F%2Fmedia.zooplus.com%2Fbilder%2F1%2F400%2F9868_luposan_kraeuterkraftb_1.jpg
)
i alarmed alien
  • 9,412
  • 3
  • 27
  • 40
  • Here is the print_r($inhalt); Array ( [id] => 303131 [name] => 12829 [artikelnummer] => 305152.4 [shop] => Zooplus [snummer] => 2 [link] => [preis] => 0 [versand] => 0 [artid] => [ean] => [bild] => [kategorie] => [cha] => [neu] => [datum] => [aktiviert] => ) – Dennis Oct 29 '14 at 21:24
  • And i still have no clue why it doesnt work. Because the record with the number 12829 is for sure available in the xml file. – Dennis Oct 29 '14 at 21:25
  • Can you do the matching on a different criterion -- e.g. does `artikelnummer` match `9868.1`? It'd be easy to pull out matches with an XPath. – i alarmed alien Oct 29 '14 at 21:30
  • I just replaced the $i = $inhalt['name']; with $i = 12829; and the script works just fine. I just don´t understand why the script doesnt work if the 12829 comes out of the db. It makes no sense to me. – Dennis Oct 29 '14 at 21:33
  • That is indeed weird! Can you var_dump($inhalt)? I wouldn't have thought this was a type issue, but best to be safe... otherwise, are there any other ways to match the db row to data in the XML file? To be honest, it would be much safer to store a unique value from the XML data in the database (e.g. `product_id`, `product_code`, etc.), so that you're not reliant on the XML file being in a specific order. – i alarmed alien Oct 29 '14 at 21:42
  • Here are the results of var_dump($inhalt); array(16) { ["id"]=> string(6) "303131" ["name"]=> string(5) "12829" ["artikelnummer"]=> string(8) "305152.4" ["shop"]=> string(7) "Zooplus" ["snummer"]=> string(1) "2" ["link"]=> string(0) "" ["preis"]=> string(1) "0" ["versand"]=> string(1) "0" ["artid"]=> string(0) "" ["ean"]=> string(0) "" ["bild"]=> string(0) "" ["kategorie"]=> string(0) "" ["cha"]=> string(0) "" ["neu"]=> string(0) "" ["datum"]=> string(0) "" ["aktiviert"]=> string(0) "" } – Dennis Oct 29 '14 at 21:49
  • The only thing i could use to match the data would be the artikelnummer. But i don´t have any experience in XPath. So i would have to check in to that first. – Dennis Oct 29 '14 at 21:50
  • I'll add an xpath version to my answer. – i alarmed alien Oct 29 '14 at 21:54
  • That would be awesome. Thank you very very much for everything. – Dennis Oct 29 '14 at 22:04
  • @Dennis No problem. I've edited the answer to put in the XPath. I think it's a better solution than matching element position--nothing beats a good old unique identifier! :^) Please click the tick by the answer -- you'll get some reputation points and it will mark the question as answered. – i alarmed alien Oct 29 '14 at 22:21