I have the following XML file
<Item>
<name>...</name>
<id>...</id>
<ImageSets>
<ImageSet Category="variant">
<SwatchImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SwatchImage>
<SmallImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SmallImage>
</ImageSet>
<ImageSet Category="primary">
<SwatchImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SwatchImage>
<SmallImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SmallImage>
</ImageSet>
</ImageSets>
</Item>
<Item>....</Item>
Then I use PHP to iterate through Item nodes within file.
foreach ($Xml as $item){
$name = $item->name;
$ID = $item->id;
};
And so on. The code works perfect extracting names and Id's for every item.
Now my problem is to extract ImageSet Category='primary'->SmallImage->URL. ImageSet nodes do not go in any particular order, so sometimes 'primary' will be first, sometimes 'variant', that's why $item->ImageSets->ImageSet[1]
is not a solution
So within my main foreach loop I've tried using xpath as follows:
$src='';
foreach ($item->ImageSets->xpath('//ImageSet[@Category="primary"]') as $img){
$src = $img->MediumImage->URL;
};
With absolutely no luck.
Any ideas would be appreciated.
Realtive to your context node $item (I have no doubt there's why you need that context node ;-)) you're looking for ImageSet that a) is a child of ImageSets (which in turn is a direct child of your context node) and b) has the attribute Category with the value primary
(which you have coded correctly)
<?php
$itemset = new SimpleXMLElement(data());
foreach ($itemset as $item) { // or something else - just some reason why you have to work with $item
foreach ($item->xpath('ImageSets/ImageSet[@Category="primary"]') as $p) {
echo $p->SwatchImage->URL;
}
}
function data() {
return <<< eox
<ItemSet>
<Item>
<name>...</name>
<id>...</id>
<ImageSets>
<ImageSet Category="variant">
<SwatchImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SwatchImage>
<SmallImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SmallImage>
</ImageSet>
<ImageSet Category="primary">
<SwatchImage>
<URL>primary swatch image url</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SwatchImage>
<SmallImage>
<URL>...</URL>
<Height Units="pixels"></Height>
<Width Units="pixels"></Width>
</SmallImage>
</ImageSet>
</ImageSets>
</Item>
<Item>...</Item>
</ItemSet>
eox;
}
You have an error in the XPath expression. If the expression starts with an /
it is relative to the document itself. You want it relative to the current node. This means you have two possible solutions
ImageSet[@Category="primary"]
This expands to child::ImageSet
. It fetches the ImageSet
element nodes that are direct children of the context node.
.//ImageSet[@Category="primary"]
Expands and normalizes to descendant::ImageSet
. It fetches any ImageSet
inside the current context, even if it is not a direct child. The .
represents the current node and //
changes the axis to descendants.