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
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" }
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>";
}
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.
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
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