4

I Use the following code to parse an XML file, with no problem:

 foreach ($xml->product as $products) { $title = $products->name; etc etc 

However, due to structure of the XML I have to use xpath on one of the nodes I need to ensure it returns the correct data

 $actors = $xml->xpath("//property[name[. ='Actors']]/value"); $actor = $actors[0]; 

This works great but it always returns the first record of the XML file where I need it to keep up with the loop, if that makes sense.

I tried the following but the same thing happens:

 $actors = $products->xpath("//property[name[. ='Actors']]/value"); 

Here is the xml in question, however my example above uses a node called name which has data Actors, swap that for Format and you have the same idea as there is a node below which is

<name>Format</name> <properties> <group> <name>Product</name> <property> <id>48546006</id> <name>Product name</name> <value>JOLLY PHONICS (JOLLY PHONICS S.)</value> </property> </group> <group> <name>Product properties</name> <property> <id>43560296</id> <name>Product Title</name> <value>JOLLY PHONICS (JOLLY PHONICS S.)</value> </property> <property> <id>43560292</id> <name>Format</name> <value>DVD</value> </property> </group> </properties> 

and here is the full foreach loop i'm using (I've omitted some of it as you don't need to read multiple things that all work correctly as you'll see:

foreach ($xml->product as $products) { // AA $title = $products->name; $PRid = $products->id; $actors = $xml->xpath("//property[./name[.='Actors']]/value[next()]"); // this ok but repeats $actors = $actors[0]; $genre = $xml->xpath("//property[name[. ='Genre']]/value"); $genre = $genre[0]; $prodcat = $products->{'category'}; $addline = mysql_query(" insert into dbname( blah blah ) VALUES ( blah blah ) ON DUPLICATE KEY UPDATE lowprice='$lowprice', highprice='$highprice'",$db); if(!$addline) { echo "cannot add to table here".mysql_error(); exit; } // debug foreach ($xml->product->retailer as $retailer) { // BB this is another foreach loop but works perfectly } // close BB } // close AA 

So, the problem is - I have nodes within the XML file that I need to extract which are always within the node called property, but, I can't simply use e.g. name[2] as they are sometimes in different places - therefore it is suggested I use xpath to get the data from the specific node I need as it's more precise - and the problem with that is that it works ok but for some reason will not simply get the data from the current node, however I try ./ or .//, it always returns the data from the first node.

Any ideas?

4
  • 1
    post sample of your xml file, it will be easier for someone to help if they see your xml. Commented Oct 7, 2011 at 13:48
  • FYI property[name = 'Actors'] and property[name[. ='Actors']] are equivalent. The former is more readable. Commented Oct 7, 2011 at 15:04
  • Other than that, I believe there is an error in the bit of PHP code that you do not show. Please post the actual loop you use. Commented Oct 7, 2011 at 15:12
  • @Tomalak full loop posted, thanks. Commented Oct 7, 2011 at 15:46

3 Answers 3

0

As I suspected (before you posted your PHP code). You do not use relative paths in a loop body. Of course this always produces the same (i.e. the absolute) result.

You must refer to $product (not $xml) with your XPath and use a relative path from there, like this:

foreach ($xml->product as $product) { // AA $title = $product->name; $PRid = $product->id; $actors = $product->xpath(".//property[name='Actors']/value"); $genre = $product->xpath(".//property[name='Genre']/value"); $prodcat = $product->{'category'}; $addline = mysql_query(" insert into dbname( blah blah ) VALUES ( blah blah ) ON DUPLICATE KEY UPDATE lowprice='$lowprice', highprice='$highprice'", $db ); if(!$addline) { echo "cannot add to table here".mysql_error(); exit; // debug } foreach ($xml->product->retailer as $retailer) { // BB this is another foreach loop but works perfectly } // close BB } // close AA 

PS: Do you really want to run the BB loop within the AA loop (or do you actually mean to loop over $product->retailer here)?

Sign up to request clarification or add additional context in comments.

2 Comments

When i try to run the new line - $actors = $product->xpath(".//property[name='Actors']/value")[0]; - I get the following: Parse error: syntax error, unexpected '[' in /home/***/***/htdocs/PRFeed_Films.php on line 30 - I run another loop inside as there are approx 10-15 product reviews within each master node which i put into a seperate db and then join when i need them with the product id I create
@Darren OK then try the assignment of [0] on a separate line. PHP cannot do this in the same statement, obviously.
0

I believe the following should work for you. Using ./ in xpath refers to the current node, rather than // as the root node:

$actors = $products->xpath("./property[name[. ='Actors']]/value"); 

It may need a little modification for your XML structure, which we can't see. But the key takeaway is using ./

UDPATE

Based on this question, try:

$actors = $products->xpath("./property/value[../name/text() = 'Actors']"); 

6 Comments

No joy I'm afraid, using $products->xpath as opposed to $xml->xpath produces nothing but tried ./ .// and leaving slashes off but still same thing
@DarrenSweeney Can you post some of your XML structure above?
./property/value[../name/text()='Actors'] is way too complicated. Better: ./property[name = 'Actors']/value
Tried that,thanks, but it simply produces an empty Array i'm afraid
@Tomalak thanks... whatever i try with ./ or .// simply produces nothing
|
0

In xpath, starting with '//' means descendant-or-self, starting at the root. You might want to try adding a '.' to the beginning to start at the current node.

$string = file_get_contents('sampleFromPost.xml'); $xml = simplexml_load_string($string); $groups = $xml->group; foreach($groups as $group) { // Changed Actors to Product Title, since Actors doesn't exist in sample. $title = $group->xpath('.//property[name="Product Title"]/value'); // -- or -- $title = $group->xpath('.//property/value[../name="Product Title"]'); // do something with the value var_dump($title); } 

1 Comment

No joy I'm afraid, using $products->xpath as opposed to $xml->xpath produces nothing but tried ./ .// and leaving slashes off but still same thing

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.