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);
Related
i have an xml file and a php file.i have received a result from an the xml file but i am not being able to get the different values of the tags.what i want is the data from individual tags.Any idea how to do it?
Here is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<users xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<user>
<id>1</id>
<username>neem99</username>
<password>dbhcasvc</password>
<email>vgwdevwe#hfvuejd.com</email>
</user>
</users>
Sample php file:
$xp = new DOMXPath( $dom );
echo var_dump($xp);
$col = $xp->query( $query );
echo var_dump($col);
$array = array();
if( $col->length > 0 ){
foreach( $col as $node) echo $node->nodeValue
}
result : 1 neem99 dbhcasvc vgwdevwe#hfvuejd.com
DOMXpath::evaluate() allows to use Xpath expressions that return scalar values. string() casts a list of nodes to a string by returning the text content of the first node.
Demo:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
// get first user id
var_dump($xpath->evaluate('string(/users/user/id)'));
//iterate all user nodes
foreach ($xpath->evaluate('/users/user') as $user) {
// get its username
var_dump($xpath->evaluate('string(username)', $user));
}
I would do like:
$doc = new DOMDocument; #$doc->load('yourFileName.xml');
$user = $doc->getElementsByTagName('user');
foreach($user as $u){
echo 'nodeName:'.$u->nodeName.'; nodeValue:'.$u->nodeValue.PHP_EOL;
}
I am trying to search an XML file of the following structure:
<Root>
<Record>
<Filenumber>12314123</Filenumber>
<StatusEN>Closed</StatusEN>
<StatusDate>02 Nov 2019</StatusDate>
</Record>
<Record>
<Filenumber>0678672301</Filenumber>
<StatusEN>Closed</StatusEN>
<StatusDate>02 Nov 2019</StatusDate>
</Record>
</Root>
I want to search based on the filenumber, but return all 3 nodes and values for the match.
I am trying
$q = '12314123';
$file = "status.xml";
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->Load($file);
$xpath = new DOMXPath($doc);
$query = "/Root/Record/Filenumber[contains(text(), '$q')]";
$entries = $xpath->query($query);
foreach ($entries as $entry) {
echo $entry->parentNode->nodeValue ;
}
This seems to return all the values I want but in one single string. How can I return them as separate variables or even better, in an array or JSON?
DOMNodeList or DOMNodeElement don't know how become an array. And that's why we must do it with our hands:
foreach ($entries as $entry) {
$result = [];
foreach ($entry->parentNode->childNodes as $node) {
$result[$node->nodeName] = $node->nodeValue;
}
var_dump($result);
}
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"
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!!
I need to get a XML File into a Database. Thats not the problem. Cant read it, parse it and create some Objects to map to the DB. Problem is, that sometimes the XML File can contain namespaces and sometimes not. Furtermore sometimes there is no namespace defined at all.
So what i first got was something like this:
<?xml version="1.0" encoding="UTF-8"?>
<struct xmlns:b="http://www.w3schools.com/test/">
<objects>
<object>
<node_1>value1</node_1>
<node_2>value2</node_2>
<node_3 iso_land="AFG"/>
<coords lat="12.00" long="13.00"/>
</object>
</objects>
</struct>
And the parsing:
$obj = new stdClass();
$nodes = array('node_1', 'node_2');
$t = $xml->xpath('/objects/object');
foreach($nodes AS $node) {
if($t[0]->$node) {
$obj->$node = (string) $t[0]->$node;
}
}
Thats fine as long as there are no namespaces. Here comes the XML File with namespaces:
<?xml version="1.0" encoding="UTF-8"?>
<b:struct xmlns:b="http://www.w3schools.com/test/">
<b:objects>
<b:object>
<b:node_1>value1</b:node_1>
<b:node_2>value2</b:node_2>
<b:node_3 iso_land="AFG"/>
<b:coords lat="12.00" long="13.00"/>
</b:object>
</b:objects>
</b:struct>
I now came up with something like this:
$xml = simplexml_load_file("test.xml");
$namespaces = $xml->getNamespaces(TRUE);
$ns = count($namespaces) ? 'a:' : '';
$xml->registerXPathNamespace("a", "http://www.w3schools.com/test/");
$nodes = array('node_1', 'node_2');
$obj = new stdClass();
foreach($nodes AS $node) {
$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.$node);
if($t[0]) {
$obj->$node = (string) $t[0];
}
}
$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.'node_3');
if($t[0]) {
$obj->iso_land = (string) $t[0]->attributes()->iso_land;
}
$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.'coords');
if($t[0]) {
$obj->lat = (string) $t[0]->attributes()->lat;
$obj->long = (string) $t[0]->attributes()->long;
}
That works with namespaces and without. But i feel that there must be a better way. Before that i could do something like this:
$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object');
foreach($nodes AS $node) {
if($t[0]->$node) {
$obj->$node = (string) $t[0]->$node;
}
}
But that just wont work with namespaces.
You could make 'http://www.w3schools.com/test/' the default namespace. This way a:objectswould match regardless of whether the document says <a:objects> or <objects>.
If memory usage is not a issue you can even do it with a textual replacement, e.g.
$data = '<?xml version="1.0" encoding="UTF-8"?>
<struct xmlns:b="http://www.w3schools.com/test/">
<objects>
<object>
<node_1>value1</node_1>
<node_2>value2</node_2>
<node_3 iso_land="AFG"/>
<coords lat="12.00" long="13.00"/>
</object>
</objects>
</struct>';
$data = str_replace( // or preg_replace(,,,1) if you want to limit it to only one replacement
'xmlns:b="http://www.w3schools.com/test/"',
'xmlns="http://www.w3schools.com/test/" xmlns:b="http://www.w3schools.com/test/"',
$data
);
$xml = new SimpleXMLElement($data);
$xml->registerXPathNamespace("a", "http://www.w3schools.com/test/");
foreach($xml->xpath('//a:objects/a:object') as $n) {
echo $n->node_1;
}
You can make your XPATH statements more generic by matching on any element * and using a predicate filter to match on the local-name(), which will match on the element name with/without namespaces.
An XPATH like this:
/*[local-name()='struct']/*[local-name()='objects']/*[local-name()='object']/*[local-name()='coords']
Applied to the code sample you were using:
$obj = new stdClass();
$nodes = array('node_1', 'node_2');
$t = $xml->xpath('/*[local-name()="objects"]/*[local-name()="object"]');
foreach($nodes AS $node) {
if($t[0]->$node) {
$obj->$node = (string) $t[0]->$node;
}
}
Take a look at This
http://blog.sherifmansour.com/?p=302
It helped me a lot.