Have XML results in plaintext, want to loop through them in PHP - php

So I am working with an API that returns results in XML. Let's just say for argument sake I am returned the following:
<?xml version="1.0" encoding="UTF-8"?>
<Properties>
<Property>
<Name>Joes Crab Shack</Name>
<Address>111 Shack Street</Address>
</Property>
<Property>
<Name>Johns Shoe Store</Name>
<Address>123 Shoe Avenue</Address>
</Property>
</Properties>
Now I am using PHP and I get the results into a variable. So essentially this happens:
$xml_results = '<?xml version="1.0" encoding="UTF-8"?><Properties><Property><Name>Joes Crab Shack</Name><Address>111 Shack Street</Address></Property><Property><Name>Johns Shoe Store</Name><Address>123 Shoe Avenue</Address></Property></Properties>';
Now how can I treat this as an XML document and for example loop through it and print out all property names?

Something like this should get the job done.
$request_xml = '<?xml version="1.0" encoding="UTF-8"?>
<Properties>
<Property>
<Name>Joes Crab Shack</Name>
<Address>111 Shack Street</Address>
</Property>
<Property>
<Name>Johns Shoe Store</Name>
<Address>123 Shoe Avenue</Address>
</Property>
</Properties>';
$xml = simplexml_load_string($request_xml);
$i = 0;
while ($xml->Property[$i])
{
echo $xml->Property[$i]->Name;
echo $xml->Property[$i]->Address;
$i++;
}

Deserialize into an xml tree, try SimpleXML. That way you can access that data in a more convenient fashion and grab specific xml elements..

Related

Getting exact data from xml to array [PHP]

i m trying to get some data from the xml out of prestashop api
To be exact, i want to create an array which will have as key the id (ex. 2) and value the name->language.
I am using simplexml_load_string to convert the xml to arrays
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<category>
<id>
<![CDATA[2]]>
</id>
...
<name>
<language id="1" xlink:href="https://mosty.com/api/languages/1">
<![CDATA[Home]]>
</language>
</name>
<link_rewrite>
<language id="1" xlink:href="https://mosty.com/api/languages/1">
<![CDATA[home]]>
</language>
</link_rewrite>
...
</category>
</prestashop>
Please have a look at the code below. I suppose you have multiple <category> elements:
Code
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<category>
<id>
<![CDATA[2]]>
</id>
<name>
<language id="1" xlink:href="https://mosty.com/api/languages/1">
<![CDATA[Home]]>
</language>
</name>
<link_rewrite>
<language id="1" xlink:href="https://mosty.com/api/languages/1">
<![CDATA[home]]>
</language>
</link_rewrite>
</category>
</prestashop>';
$obj = simplexml_load_string($xml);
$result = [];
foreach($obj->category as $item) {
$result[trim($item->id)] = trim($item->name->language);
}
var_dump($result);
Output
array(1) { [2]=> string(4) "Home" }

How to parse XML-file to array and retrieve all children of an child with specific attribute in PHP?

my XML-file is as follows: agents.xml
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
</agents>
I want to retrieve all child elements of an agent, selected by attribute value "id". I tried the following, passing a the variable "id" to the script:
$agents_xml = simplexml_load_file("/<path_to>/agents.xml");
$json = json_encode($agents_xml);
$array = json_decode($json,TRUE);
//decrement id for correct index
$id=$id-1;
//I want to return in JSON format
$testarr=json_encode($array['agent'][$id]);
echo $testarr;
When "id" has value 1, i got this:
{"#attributes":{"id":"1"},"aname":"pi1","alive":"0","scenarios":"1,2,3"}
But i know, if the XML is disordered like:
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
</agents>
This is not very reliable.
Thanks for any idea!
Try
$str = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<agents>
<agent id="1">
<aname>pi1</aname>
<alive>0</alive>
<scenarios>1,2,3</scenarios>
</agent>
<agent id="2">
<aname>pi2</aname>
<alive>1</alive>
<scenarios>4,5,6</scenarios>
</agent>
</agents>
XML;
$xml = new SimpleXMLElement($str);
foreach($xml->agent as $agent)
{
var_dump($agent);
echo "<hr>";
}

How do I delete XML nodes in PHP based on the information inside of it?

Preface: There are many questions similar to this that I've scoured through profusely. Nothing can quite answer what I need to do.
Here is my data structure. (obviously simplified)
<Upload>
<tickets>
<ticket>
<ticket_number>123</ticket_number>
<clerk>001</clerk>
<property>
<item>
<item_number>1</item>
<jewelry_metal>GOLD</jewelry_metal>
</item>
<item>
<item_number>2</item>
<jewelry_metal>SILVER</jewelry_metal>
</item>
</property>
</ticket>
<ticket>
<ticket_number>456</ticket_number>
<clerk>001</clerk>
<property>
<item>
<item_number>1</item>
<jewelry_metal></jewelry_metal>
</item>
</property>
</ticket>
<tickets>
<Upload>
I need to check the first item in each ticket, and if the <jewelry_metal> tag is empty, delete the entire <ticket>. I'm open to any suggestions at this point.
Your best bet here would be to use XPath and DomDocument. Try this:
<?php
$xmlstr = <<<XML
<?xml version='1.0'?>
<Upload>
<tickets>
<ticket>
<ticket_number>123</ticket_number>
<clerk>001</clerk>
<property>
<item>
<item_number>1</item_number>
<jewelry_metal>GOLD</jewelry_metal>
</item>
<item>
<item_number>2</item_number>
<jewelry_metal>SILVER</jewelry_metal>
</item>
</property>
</ticket>
<ticket>
<ticket_number>456</ticket_number>
<clerk>001</clerk>
<property>
<item>
<item_number>1</item_number>
<jewelry_metal></jewelry_metal>
</item>
</property>
</ticket>
</tickets>
</Upload>
XML;
$doc = new DOMDocument();
$doc->loadxml($xmlstr);
$xpath = new DOMXpath($doc);
foreach($xpath->query('//tickets/ticket/property/item[1]') as $key => $item) {
if (empty($item->getElementsByTagName('jewelry_metal')->item(0)->nodeValue)) {
$item->parentNode->removeChild($item);
}
}
echo $doc->saveXML();
The output will be:
<?xml version="1.0"?>
<Upload>
<tickets>
<ticket>
<ticket_number>123</ticket_number>
<clerk>001</clerk>
<property>
<item>
<item_number>1</item_number>
<jewelry_metal>GOLD</jewelry_metal>
</item>
<item>
<item_number>2</item_number>
<jewelry_metal>SILVER</jewelry_metal>
</item>
</property>
</ticket>
<ticket>
<ticket_number>456</ticket_number>
<clerk>001</clerk>
<property>
</property>
</ticket>
</tickets>
</Upload>
Hope this helps!
I would suggest you use the Xpath language for that. Lets translate:
I need to check the first item in each ticket, and if the <jewelry_metal> tag is empty, delete the entire <ticket>
into xpath:
//ticket[.//item[1]/jewelry_metal = ""]
That will query all elements to delete. To run such an xpath query in PHP with simplexml and then delete the elements is explained in this question:
PHP SimpleXML - Remove xpath node
Ensure you've got error reporting enabled because your XML you've provided in question is totally broken. Just in case you didn't notice.

PHP SimpleXML add child to each parent repeatedly

I have this kind of XML:
<?xml version="1.0" encoding="utf-8"?>
<data>
<stats>
</stats>
<params>
</params>
<results>
<record id='SJDGH'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
<record id='OIIO'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
</results>
</data>
I'm generating a new <item> for every <record> in <results> in a loop:
// $data is SimpleXml objec from XML above
foreach ($data->results->record as $record)
{
$newitem = 'New item!'.time().$record->attributes()->id;
}
Somehow in this loop i need to change the SimpleXML object ($data) to contain new items in every <record>.
is it possible?
I needed a little guessing, but this might what you're looking for:
$records = $data->results->record;
foreach($records as $record)
{
$value = sprintf('New Item! %s / id:%s', time(), $record['id']);
$record->item[] = $value;
}
$data->asXML('php://output');
See it in action.
I think you might want to use addChild.
Check it out here: http://php.net/manual/en/simplexmlelement.addchild.php

PHP SimpleXMLElement not parsing <title> node

I have a simple well-formed XML doc that I'm writing to the page using PHP. For some reason the output never includes the title node, and after researching I can't figure this out. If I change the title node to 'heading' or some other name it is included in the output, but when its named 'title', this node is skipped.
Here's the XML doc code...
<?xml version="1.0" encoding="UTF-8"?>
<items>
<product>
<id>cd1</id>
<title>CD One</title>
<description>This is my first CD</description>
<img>/images/sample.jpg</img>
<price>14.99</price>
</product>
</items>
The PHP code looks like this...
<?php
$filename = '../catalog.xml';
$contents = file_get_contents($filename);
echo $contents;
?>
Well, the XML you posted is not valid XML;
The encoding should be in lowercase. Try with this string:
<?xml version="1.0" encoding="utf-8"?>
<items>
<product>
<id>cd1</id>
<title>CD One</title>
<description>This is my first CD</description>
<img>/images/sample.jpg</img>
<price>14.99</price>
</product>
</items>
Validate here: http://validator.w3.org/check

Categories