0
votes

I need a little help to figure out XPath search inside XML output simple_xml_load in PHP. I have this XML:

<PRODUCTS>
  <PRODUCT>
    <CODE>5009444</CODE>
    <NAME>Prova</NAME>
    <IMG>prova.jpg</IMG>
  </PRODUCT>
  ....
  ....
</PRODUCTS>

I want to filter and iterate through this data to find and return all occurrences with a variable code. I used this syntax but didn't work

$id = 1;
$struct = \App\Models\Structures::where('id', $id)->first();
$url = 'http://demo.villaggissimi.it/public/xml/CMP_' . $struct->operators->pk .'.xml';
$xc = simplexml_load_file($url) or die("Non sono stati trovati risultati");
$xml2 = $xc->xpath("/PRODUCTS/PRODUCT[CODE='$struct->code']");
return response()->json($xml2);
1
Find all occurences of what exactly?Jerodev
i need to iterate trough results that have same "CODE" value. But i don't want to use foreach and if statement but directly xpathwwhitewalter
CODE is a node name not an attribute, so your XPath is wrong as it is handling it as an attribute.Patrick Mevzek
@PatrickMevzek, if it was an attribute - you would be using [@CODE= in XPathNigel Ren
Please be more specific than "didn't work". Show us a minimal reproducible example - a small document we can actually test with, with the output you want, the relevant code (we don't need to know about $url and $struct), and the output you got.IMSoP

1 Answers

0
votes

The result of the Xpath Expression is a node list, SimpleXMLElement:xpath() only supports that kind of result, it will always return an array of SimpleXMLElement objects (for a valid Xpath expression).

So you still have to use foreach()/if() to avoid an error message if no element has been found.

You can however limit the result to a list with only a single node.

foreach ($xc->xpath("/PRODUCTS/PRODUCT[CODE='$struct->code'][1]") as $productNode) {
  return response()->json($productNode);
}
return FALSE;

$productNodes = $xc->xpath("/PRODUCTS/PRODUCT[CODE='$struct->code'][1]");
if (count($productNodes) > 0) {
  return response()->json($productNodes[0]);
}
return FALSE;