I am trying to learn how to use XMLReader with SimpleXML to read a large xml file and to be able to retrieve various data from it. My problem is retrieving data from elements by their attribute.
For example if i have the XML:
<Product>
<CustomParameter Name="companyName">Company A</CustomParameter>
<CustomParameter Name="productName">Shiny Black Shoes</CustomParameter>
<CustomParameter Name="productUrl">http://www.example.com</CustomParameter>
<CustomParameter Name="companyUrl">http://www.example.com</CustomParameter>
</Product>
<Product>
<CustomParameter Name="companyName">Company B</CustomParameter>
<CustomParameter Name="productName">Boots</CustomParameter>
<CustomParameter Name="productUrl">http://www.example.com</CustomParameter>
<CustomParameter Name="companyUrl">http://www.example.com</CustomParameter>
</Product>
I want to only retrieve the data for the CustomParameter with the name="productName" attribute.
I am using this code, but its only displaying the first found CustomParameter.
$z = new XMLReader;
$z->open('products.xml');
$doc = new DOMDocument;
$product_name = array();
// move to the first <product /> node
while ($z->read() && $z->name !== 'Product');
while ($z->name === 'Product')
{
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
$product_name[] = $node->CustomParameter;
$z->next('Product');
}
$product_name = array_unique($product_name);
foreach($product_name as $value)
echo $value."\n";
Can someone explain how to read the specific one I want?
Thanks
In the product while
loop, you could iterate over each of the CustomParameter tags, testing for the attribute value, like this:
while ($z->name === 'Product')
{
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
foreach($node->children() as $child) {
if ($child["Name"] == "productName") {
$product_name[] = (string) $child;
}
}
$z->next('Product');
}
However, you could make your code a lot shorter if you would use an xpath
search, like this:
$xmlDoc = simplexml_load_file('products.xml');
// locate the nodes of interest through an XPath descriptor:
$result = $xmlDoc->xpath('/Products/Product/CustomParameter[@Name="productName"]');
while(list( , $node) = each($result)) {
$product_name[] = (string) $node;
}
In the above code you should replace the XPath value with the true path to your elements. Since you did not provide the whole XML document, I just assumed the Product tags appear in a Products (plural) wrapper tag, which is the root element. Of course, your actual situation can be different, but it should be easy to adapt to.