Parse XML to PHP using ID value - php

How can I echo xml values with php by calling their "columnId" and not the position in the array ? (The array is really long)
Here is a sample of the xml :
<Data>
<Value columnId="ITEMS_SOLD">68</Value>
<Value columnId="TOTAL_SALES">682</Value>
<Value columnId="SHIPPING_READY">29</Value>
...
</Data>
The following php gives me all of the values :
$url = 'XXX';
$xml = file_get_contents($url);
$feed = simplexml_load_string($xml) or die("Error: Cannot create object");
foreach($feed->Data->Value as $key => $value){
echo $value;
}
I would like to be able to use something like that in my document :
echo $feed->Data->Value['TOTAL_SALES'];
Thank you for your help.

echo $feed->Data->Value[1];

I have an another way for your solution. You can convert xml object into array and use this for further process. Try this code:
<?php
$url = 'XXX';
//Read xml data, If file exist...
if (file_exists($url)) {
//Load xml file...
$xml = simplexml_load_file($url);
$arrColumn = array();//Variable initialization...
$arrFromObj = (array) $xml;//Convert object to array...
$i = 0;//Variable initialization with value...
//Loop until data...
foreach($xml AS $arrKey => $arrData) {
$columnId = (string) $arrData['columnId'][0];//array object to string...
$arrColumn[$columnId] = $arrFromObj['Value'][$i];//assign data to array...
$i++;//Incremental variable...
}
} else {//Condition if file not exist and display message...
exit('Failed to open file');
}
?>
Above code will store result into array variable $arrColumn and result is:
Array
(
[ITEMS_SOLD] => 68
[TOTAL_SALES] => 682
[SHIPPING_READY] => 29
)
Hope this help you well!

Use XPath. SimpleXML and DOM support it, but SimpleXML has some limits (It can only fetch node lists).
SimpleXML
$feed = simplexml_load_string($xml);
var_dump(
(string)$feed->xpath('//Value[#columnId = "TOTAL_SALES"]')[0]
);
Output:
string(3) "682"
DOM
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
var_dump(
$xpath->evaluate('string(//Value[#columnId = "TOTAL_SALES"])')
);
Output:
string(3) "682"

Related

Get elements from a XML content by PHP

I am trying to get elements from this XML content but returns empty:
<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>
And this is my code to extract element type of grammar :
$dom = new DOMDocument();
$dom->loadXml($output);
$params = $dom->getElementsByTagName('error'); // Find Sections
$k=0;
foreach ($params as $param) //go to each section 1 by 1
{
if($param->type == "grammar"){
echo $param->description;
}else{
echo "other type";
}
Problem is the script returns empty.
you can use simplexml_load_string()
$output = '<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>';
$xml = simplexml_load_string($output);
foreach($xml->error as $item)
{
//echo (string)$item->type;
if($item->type == "grammar"){
echo $item->description;
}else{
echo "other type";
}
}
You apparently haven't configured PHP to report errors because your code triggers:
Notice: Undefined property: DOMElement::$type
You need to grab <type> the same way you grab <error>, using DOM methods like e.g. getElementsByTagName(). Same for node value:
if ($param->getElementsByTagName('type')->length && $param->getElementsByTagName('type')[0]->nodeValue === 'grammar') {
// Feel free to add additional checks here:
echo $param->getElementsByTagName('description')[0]->nodeValue;
}else{
echo "other type";
}
Demo
I think is this what you want.
<?php
$output = '<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>';
$dom = new DOMDocument();
$dom->loadXml($output);
$params = $dom->getElementsByTagName('error'); // Find Sections
$k=0;
foreach ($params as $param) //go to each section 1 by 1
{
$string = $param->getElementsByTagName( "string" )->item(0)->nodeValue;
$description = $param->getElementsByTagName( "description" )->item(0)->nodeValue;
$option = $param->getElementsByTagName( "option" )->item(0)->nodeValue;
$type = $param->getElementsByTagName( "type" )->item(0)->nodeValue;
echo $type;
if($type == "grammar"){
echo $description ;
}else{
echo "other type";
}
}
?>
You're mixing DOM with SimpleXML. This is possible, but you would need to convert the DOM element node into a SimpleXML instance with simplexml_import_dom().
Or you use Xpath. getElementsByTagName() is a low level DOM method. Using Xpath expressions allows for more specific access with a lot less code.
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('//error') as $error) {
var_dump(
[
'type' => $xpath->evaluate('string(type)', $error),
'description' => $xpath->evaluate('string(description)', $error)
]
);
}
Output:
array(2) {
["type"]=>
string(7) "grammar"
["description"]=>
string(16) "Make I uppercase"
}
Xpath expressions allow for conditions as well, for example you could fetch all grammar errors using //error[#type = "grammar"].

Simplexml get node by attribute

I've got xml file:
<?xml version="1.0" ?>
<xml>
<opis lang="en">My text</opis>
<opis lang="cz">My text2</opis>
</xml>
I want to get "My text2" - so a node where attribute lang is "cz":
$xml = simplexml_load_file($fileName);
$result = $xml->xpath('//xml/opis[#lang="cz"]')
but instead of value I get:
array(1) (
[0] => SimpleXMLElement object {
#attributes => array(1) (
[lang] => (string) cz
)
}
))
You could get the value like this:
$xml = simplexml_load_file($fileName);
$result = $xml->xpath('//xml/opis[#lang="cz"]');
foreach($result as $res) {
echo $res;
}
Try using DomDocument:
$xml = new DomDocument;
$xml->load('yourFile');
$xpath = new DomXpath($xml);
foreach ($xpath->query('//xml/opis[#lang="cz"]') as $rowNode) {
echo $rowNode->nodeValue; // will be 'this item'
}

inserting an object into an array of objects php

I am trying to write a php script which will insert an object into an array of objects which is originally in XML format. I need to insert the object at a specified index and then be able to re-write the xml file from which the data was pulled with the updated object. Here is the structure of my XML
<?xml version="1.0" encoding="UTF-8"?>
<Bars>
<Bar>
<BarName>Kam's</BarName>
<bar_id>0</bar_id>
<Bartenders>
<Bartender>
<fname>Max</fname>
<lname>Vest</lname>
<imageURL>http://uofi-bars.com/bartenderImages/maxvest.jpg</imageURL>
<shift>2</shift>
</Bartender>
</Bartenders>
<Events>
<Event>
<EventName>Kams event</EventName>
<date>08/10/1989</date>
</Event>
</Events>
<Specials>
<Special>Kam's Special 1</Special>
<Special>Kam's Special 2</Special>
</Specials>
</Bar>
So in other words, if I have a bartender who works at a bar with an id of bar_id = 0, I need to be able to insert that bartender into the array of bartenders for that particular bar.
I use the following php code to create the arrays from XML:
function objectsIntoArray($arrObjData, $arrSkipIndices = array())
{
$arrData = array();
// if input is object, convert into array
if (is_object($arrObjData)) {
$arrObjData = get_object_vars($arrObjData);
}
if (is_array($arrObjData)) {
foreach ($arrObjData as $index => $value) {
if (is_object($value) || is_array($value)) {
$value = objectsIntoArray($value, $arrSkipIndices); // recursive call
}
if (in_array($index, $arrSkipIndices)) {
continue;
}
$arrData[$index] = $value;
}
}
return $arrData;
}
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
I guess I just don't know how to refer to this array of objects within an array of objects... Any help would be greatly appreciated!
Thanks!
if you just replace your code:
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
with this:
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xml = new SimpleXMLElement($xmlStr);
$bartenders = $xml->xpath('//Bartenders');
$new_bartender = $bartenders[0]->addChild('Bartender');
$new_bartender->fname = 'test1';
$new_bartender->lname = 'test2';
$new_bartender->imgURL = 'http://test.com';
$new_bartender->shift = '0';
print_r($bartenders);
this should do the trick, just replace the values with appropriate values :) i hope this helps!!

passing xml in php function and getting common xml with condition [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best XML Parser for PHP
-----First XML-----str1
<HOME>
<USER_DETAIL>
<LOCATION><![CDATA[MUMBAI]]></LOCATION>
<NAME><![CDATA[RAVI]]></NAME>
<ID><![CDATA[101]]></ID>
</USER_DETAIL>
<USER_DETAIL>
<LOCATION><![CDATA[PUNE]]></LOCATION>
<NAME><![CDATA[MANISH]]></NAME>
<ID><![CDATA[102]]></ID>
</USER_DETAIL>
</HOME>
---Second XML----str2
<USER_DATA>
<DATA>
<DOB><![CDATA[2/11/1959]]></DOB>
<STATUS><![CDATA[single]]></STATUS>
<PROFILE_PIC><![CDATA[101.JPG]]></PROFILE_PIC>
<ID><![CDATA[101]]></ID>
</DATA>
<DATA>
<DOB><![CDATA[6/8/1987]]></DOB>
<STATUS><![CDATA[married]]></STATUS>
<PROFILE_PIC><![CDATA[102.JPG]]></PROFILE_PIC>
<ID><![CDATA[102]]></ID>
</DATA>
</USER_DATA>
I am new to XML.
I have two xml as above I want common xml with all the data of user. In two XML common thing is ID of user. so is there any way to pass xml into function and compare the id in second xml and get the detais of that perticular user and forms a required(Common with all detais) xml.
str1 and str2 is the php variable which contains the above xml respectively.
use below codes to generate a new XML, you can change the nodes based on your requirements. in case you have both XMLs in a file you can use simplexml_load_file($filename); to load the XML and assign it to $str1 and $str2
$str1 = "<HOME>
<USER_DETAIL>
<LOCATION><![CDATA[MUMBAI]]></LOCATION>
<NAME><![CDATA[RAVI]]></NAME>
<ID><![CDATA[101]]></ID>
</USER_DETAIL>
<USER_DETAIL>
<LOCATION><![CDATA[PUNE]]></LOCATION>
<NAME><![CDATA[MANISH]]></NAME>
<ID><![CDATA[102]]></ID>
</USER_DETAIL>
</HOME>";
$str2 = "<USER_DATA>
<DATA>
<DOB><![CDATA[2/11/1959]]></DOB>
<STATUS><![CDATA[single]]></STATUS>
<PROFILE_PIC><![CDATA[101.JPG]]></PROFILE_PIC>
<ID><![CDATA[101]]></ID>
</DATA>
<DATA>
<DOB><![CDATA[6/8/1987]]></DOB>
<STATUS><![CDATA[married]]></STATUS>
<PROFILE_PIC><![CDATA[102.JPG]]></PROFILE_PIC>
<ID><![CDATA[102]]></ID>
</DATA>
</USER_DATA>";
$xml1 = simplexml_load_string($str1);
$xml2 = simplexml_load_string($str1);
//print_r($xml);
$tempArr = array();
foreach( $xml1 as $obj) {
$id = $obj->ID;
$tempArr["$id"]['LOCATION'] = (string)$obj->LOCATION;
$tempArr["$id"]['NAME'] = (string)$obj->NAME;
}
foreach( $xml2 as $obj) {
$id = $obj->ID;
$tempArr["$id"]['DOB'] = (string)$obj->DOB;
$tempArr["$id"]['STATUS'] = (string)$obj->STATUS;
$tempArr["$id"]['PROFILE_PIC'] = (string)$obj->PROFILE_PIC;
}
//print_r($tempArr);
$xml = new DOMDocument('1.0', 'iso-8859-1');
$doc = $xml->createElement('DOCUMENT');
$doc = $xml->appendChild($doc);
foreach( $tempArr as $ky=>$val ) {
$rnod = $xml->createElement('USER_DETAIL');
$rnod = $doc->appendChild($rnod);
//$rnod = $xml->appendChild($rnod);
$dataN0 = $xml->createElement('ID');
$dataN0 = $rnod->appendChild($dataN0);
$nodV = $xml->createTextNode($ky);
$dataN0->appendChild($nodV);
foreach($val as $k=>$v) {
$dataN1 = $xml->createElement($k);
$dataN1 = $rnod->appendChild($dataN1);
$nodV1 = $xml->createTextNode($v);
$dataN1->appendChild($nodV1);
}
}
$newXml = $xml->saveXML();
echo htmlspecialchars($newXml);

PHP XML file filter on match

I am having a heck of a time getting this working...
What I want to do is filter a xml file by a city (or market in this case).
This is the xml data.
<itemset>
<item>
<id>2171</id>
<market>Vancouver</market>
<url>http://</url></item>
<item>
<id>2172</id>
<market>Toronto</market>
<url>http://</url></item>
<item>
<id>2171</id>
<market>Vancouver</market>
<url>http://</url></item>
This is my code...
<?php
$source = 'get-xml-feed.php.xml';
$xml = new SimpleXMLElement($source);
$result = $xml->xpath('//item/[contains(market, \'Toronto\')]');
while(list( , $node) = each($result)) {
echo '//Item/[contains(Market, \'Toronto\')]',$node,"\n";
}
?>
If I can get this working I would like to access each element, item[0], item[1] base on filtered results.
Thanks
I think this implements what you are looking for using XPath:
<?php
$source = file_get_contents('get-xml-feed.php.xml');
$xml = new SimpleXMLElement($source);
foreach ($xml as $node)
{
$row = simplexml_load_string($node->asXML());
$result = $row->xpath("//item/market[.='Toronto']");
if ($result[0])
{
var_dump($row);
}
}
?>
As another answer mentioned, unless you are wed to the use of XPath it's probably more trouble than it's worth for this application: just load the XML and treat the result as an array.
I propose using simplexml_load_file. The learning curve is less step than using the specific XML objects + XPath. It returns an object in the format you descibe.
Try this and you'll see what I mean:
<?php
$source = 'get-xml-feed.php.xml';
$xml = simplexml_load_file($source);
var_dump($xml);
?>
There is also simplexml_load_string if you just have an XML snippet.
<?php
$source = 'get-xml-feed.php.xml';
//$xml = new SimpleXMLElement($source);
$dom = new DOMDocument();
#$dom->loadHTMLFile($source);
$xml = simplexml_import_dom($dom);
$result = $xml->xpath("//item/market[.='Toronto']/..");
while(list( , $node) = each($result)) {
print_r($node);
}
?>
This will get you the parent nodeset when it contains a node with "Toronto" in it. It returns $node as a simplexml element so you will have to deal with it accordingly (I just printed it as an array).

Categories