Trying to parse the following xml:
<?xml version="1.0"?>
<devices>
<device name="TEMP" index="0" available="1" type="" id="xxx">
<field type="2" max="50" min="-20" niceName="Temperature (C)" value="24.75" key="TempC"/>
<field type="2" max="122" min="-4" niceName="Temperature (F)" value="76.55" key="TempF"/>
and pull the TempF value of 76.55.
This is the code I was trying, but I'm not doing something isn't right:
$xml = simplexml_load_file('c:\data.xml') or die("Error: Cannot create object");
echo '<h2>Server Temperature</h2>';
$list = $xml->devices;
for ($i = 0; $i < count($list); $i++) {
echo 'Temp: ' .$list[$i]->TempF[value] . '<br>';
You can loop $devices->device instead without instead of using a for loop
echo '<h2>Server Temperature</h2>';
foreach ($xml->device as $device) {
foreach ($device->field as $field) {
$att = $field->attributes();
if ((string)$att->key === "TempF") {
echo 'Temp: ' . $field->attributes()->value . "<br>";
}
}
}
Output
<h2>Server Temperature</h2>Temp: 76.55<br>
See a Php demo
Or if you want to loop all the values of field, you can use xpath:
echo '<h2>Server Temperature</h2>';
foreach ($xml->xpath('/devices/device/field[#key="TempF"]/#value') as $value) {
echo 'Temp: ' . $value . "<br>";
}
Output
<h2>Server Temperature</h2>Temp: 76.55<br>
See another Php demo
Related
I am having a hard time trying to understand why I can't compare the values of two arrays in PHP. If I echo both of these during the loop using "echo $description->ItemDesriptionName;" and "echo $item->ItemName;" the values seem to show as the same, but when I try to compare them using if, nothing works. What am I missing?
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
echo $item->ItemName . ' - ' . $item->Price . '</br>';
foreach ($itemdescription as $description) {
if ($description->ItemDescriptionName == $item->ItemName) {
echo 'We have a match!';
//where I would echo $description->ItemDescription;
}
}
}
?>
Here is the XML file
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Menu>
<Categories>
<Name>Category 1</Name>
<Items>
<ItemObject>
<ItemName>Item 1</ItemName>
<Price>1</Price>
</ItemObject>
<ItemObject>
<ItemName>Item 2</ItemName>
<Price>3</Price>
</ItemObject>
</Items>
</Categories>
<Options>
<Description>
<DescriptionObject>
<ItemDescriptionName>Item 1</ItemDescriptionName>
<ItemDescription>A Great item</ItemDescription>
</DescriptionObject>
<DescriptionObject>
<ItemDescriptionName>Item 2</ItemDescriptionName>
<ItemDescription>A Great item as well</ItemDescription>
</DescriptionObject>
</Description>
</Options>
</Menu>
</Root>
compare as string
and you have typo in ItemDescriptioName (ItemDescriptionName)
if ( (string)$description->ItemDescriptionName == (string)$item->ItemName) {
Convert to string and then compare
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$menu = $xml->Menu;
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
$itemname = $item->ItemName;
foreach ($itemdescription as $description) {
$descriptionname = $description->ItemDescriptionName ;
echo $itemname." ---- ".$descriptionname."<br/>";
if((string)$itemname === (string)$descriptionname){
echo "Yes its matched";
}
}
}
?>
Working fine for me
The properties like $description->ItemDescriptionName are SimpleXMLElement objects. So you do not compare strings but two objects.
SimpleXMLElement objects implement the magic method __toString(). They can be cast to string automatically, but a compare between to objects will not trigger that. You can force it:
if ((string)$description->ItemDescriptionName === (string)$item->ItemName) {
...
Can you access them directly instead using an accordant index?
...
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description;
$i = 0;
foreach ($items as $item) {
echo $i.' '.$item->ItemName . ' - ' . $item->Price;
echo $itemdescription->DescriptionObject[$i]->ItemDescriptionName[0];
echo ' ';
echo $itemdescription->DescriptionObject[$i]->ItemDescription[0];
echo '</br>';
$i++;
}
I am trying to access the 'field' element in the 'criteria' node in the following XML:
<?xml version="1.0" encoding="utf-8"?>
<result>
<product>
<data>
<field>spr_tech1</field>
<value>S7</value>
<criteria field="xfield_3">
<criteria_list>Green</criteria_list>
<criteria_list>Beige</criteria_list>
</criteria>
</data>
<data>
<field>spr_tech1</field>
<value>S1</value>
<criteria field="xfield_3">
<criteria_list>Red</criteria_list>
<criteria_list>Blue</criteria_list>
<criteria_list>Yellow</criteria_list>
</criteria>
</data>
<data>
<field>spr_tech1</field>
<value>S7</value>
<criteria field="xfield_3">
<criteria_list>Green</criteria_list>
</criteria>
<criteria field="tech_rt2">
<criteria_list>Transistor</criteria_list>
</criteria>
</data>
</product>
</result>
The code below results in the following error:
Fatal error: Call to a member function attributes() on a non-object
function parseXmlFile($filename)
{
$xml = file_get_contents($filename);
$obj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$array = json_decode(json_encode($obj), true); // Convert to array}
return $array;
}
$xform = parseXmlFile('transformations.xml');
foreach ($xform['product']['data'] as $data)
{
echo (string)$data['field'] . '<br>';
echo (string)$data['value'] . '<br>';
foreach($data['criteria']->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data['criteria']->attributes()->{'field'} . '<br>';
foreach($data['criteria']['criteria_list'] as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo "-----------------------------------<br>";
}
print "<pre>";
print_r($xform);
print "</pre>";
I've tried a couple methods as you can see in the code, but neither are working for me.
Any help is appreciated!
It seems the problem is when you load the file.
I tried it with file_get_contents() See below
$xml_content = file_get_contents('path to your XML file');
$xform = simplexml_load_string($xml_content);
foreach ($xform['product']['data'] as $data)
{
echo (string)$data['field'] . '<br>';
echo (string)$data['value'] . '<br>';
foreach($data['criteria']->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data['criteria']->attributes()->{'field'} . '<br>';
foreach($data['criteria']['criteria_list'] as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo "-----------------------------------<br>";
}
print "<pre>";
print_r($xform);
print "</pre>";
Your parseXmlFile function can be replaced completely with the built-in simplexml_load_file():
it loads the contents with file_get_contents first; simplexml_load_file vs simplexml_load_string will do this for you
it forces the LIBXML_NO_CDATA option, which is almost certainly not something you need; to get the text contents of a SimpleXML object - including CDATA - you use (string)$node
it converts the incredibly useful SimpleXML object into an array that will be missing half of the data and much worse to work with
To understand SimpleXML, look at the examples in the manual. Elements are accessed with ->name and attributes with ['name'].
So:
$xform = simplexml_load_file('transformations.xml');
foreach ($xform->product->data as $data)
{
echo (string)$data->field . '<br>';
echo (string)$data->value . '<br>';
foreach($data->criteria->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data->criteria['field'] . '<br>';
foreach($data->criteria->criteria_list as $number => $node)
{ echo $number . ' = ' . (string)$node . '<br>'; }
echo "-----------------------------------<br>";
}
I am trying to display attributes foreach global_ivr_variable:
$xml = '
<response method="switchvox.ivr.globalVariables.getList">
<result>
<global_ivr_variables>
<global_ivr_variable id="1" name="cid_name" value="Smith" />
<global_ivr_variable id="2" name="Q_ID_Global" value="COS" />
</global_ivr_variables>
</result>
</response>
';
$sxml = simplexml_load_string($xml);
foreach($sxml->result->global_ivr_variables->global_ivr_variable->attributes() as $a => $b)
{
echo $a .'=' . $b . "<br>";
}
All I get is the attributes of the first node:
id="1"
name="cid_name"
value="Smith"
I've also tried the following, which gives me no values at all...
foreach($sxml->result->global_ivr_variables as $xvar)
{
$a = $xvar->global_ivr_variable->id;
$b = $xvar->global_ivr_variable->name;
$c = $xvar->global_ivr_variable->value;
echo 'a='.$a.', b='.$b.', c='.$c.'<br>';
}
a=, b=, c=
Thank you all who step up to help the needy!
You almost had it but you need to iterate through each of the <global_ivr_variable> elements and then pull out the attributes:
foreach($sxml->result->global_ivr_variables->global_ivr_variable as $variable)
{
foreach($variable->attributes() as $a => $b)
{
echo $a .'=' . $b . "<br>";
}
}
If you make use of PHP variables, those problems normally easily disappear because your code is more readable.
Additionally you can access the attributes in SimpleXML via array-notation:
$variables = $sxml->result->global_ivr_variables->global_ivr_variable;
foreach ($variables as $variable)
{
printf("%s = %s\n", $variable['name'], $variable['value']);
}
This gives the following output:
cid_name = Smith
Q_ID_Global = COS
As you know upfront for which attributes you're looking for, your code is much more clear and stable by using those names.
However, if you're looking for just all attributes of the global_ivr_variable elements, then it's easier to iterate over them with XPath:
$allAttributes = $sxml->xpath('//global_ivr_variable/#*');
foreach ($allAttributes as $attribute) {
printf("%s = %s\n", $attribute->getName(), $attribute);
}
This then gives the following output:
id = 1
name = cid_name
value = Smith
id = 2
name = Q_ID_Global
value = COS
Here is the full code-example:
$xml = <<<XML
<response method="switchvox.ivr.globalVariables.getList">
<result>
<global_ivr_variables>
<global_ivr_variable id="1" name="cid_name" value="Smith" />
<global_ivr_variable id="2" name="Q_ID_Global" value="COS" />
</global_ivr_variables>
</result>
</response>
XML;
$sxml = simplexml_load_string($xml);
$variables = $sxml->result->global_ivr_variables->global_ivr_variable;
foreach ($variables as $variable)
{
printf("%s = %s\n", $variable['name'], $variable['value']);
}
echo "----\n";
$allAttributes = $sxml->xpath('//global_ivr_variable/#*');
foreach ($allAttributes as $attribute) {
printf("%s = %s\n", $attribute->getName(), $attribute);
}
My XMLfile is as follows:
<Project>
<ProjectInformation>
<FileHeader>IDGIS_PROJECT</FileHeader>
<Details ProjectID="0" ProjectName="" Description="" StartDate="02/05/2012 00:00:00 AM" OwnerShip="" LastModified="01/01/0001 00:00:00 AM" Datum="WGS_84" Projection="CYL" NoSignificantDecimals="3" ZoomCurrent="303601" RasterHeight="0" Background="-1">Project Details</Details>
<ProjectBounds XMin="25.4579486950873" YMin="44.7183808936148" XMax="26.5953949808977" YMax="45.5345534542584" ExtentBounds="no">Bounds</ProjectBounds>
</ProjectInformation>
<Layers>
<Layer ID="2" Description="" MinZoom="1" MaxZoom="1000000000" Visible="3" RemotHostType="LocalFile" RemotHost="" FolderName="Prahova_Highways" Path="" LayerStatus="ReadWrite">
</Layers>
I am unable to get child notes of Projectinformation. i want to get all attributes of Details and Project bounds. This thing is very easy in Java but i dunt know how to do it with php.
My code for getting childnotes of projectinformation is as follows:
$xmlDoc = new DOMDocument();
$xmlDoc->load('oglPrahova/prahova.GIS');
$x=$xmlDoc->documentElement;
var_dump($x);
$x = $xmlDoc->->getElementsByTagName('ProjectInformation');
foreach ($x->childNodes AS $item) {
print $i->nodeName . " = " . $item->nodeValue . "<br>";
}
You should use SimpleXML :
$xml = new SimpleXMLElement(
'<Project>
<ProjectInformation>
<FileHeader>IDGIS_PROJECT</FileHeader>
<Details ProjectID="0" ProjectName="" Description="" StartDate="02/05/2012 00:00:00 AM" OwnerShip="" LastModified="01/01/0001 00:00:00 AM" Datum="WGS_84" Projection="CYL" NoSignificantDecimals="3" ZoomCurrent="303601" RasterHeight="0" Background="-1">Project Details</Details>
<ProjectBounds XMin="25.4579486950873" YMin="44.7183808936148" XMax="26.5953949808977" YMax="45.5345534542584" ExtentBounds="no">Bounds</ProjectBounds>
</ProjectInformation>
<Layers>
<Layer ID="2" Description="" MinZoom="1" MaxZoom="1000000000" Visible="3" RemotHostType="LocalFile" RemotHost="" FolderName="Prahova_Highways" Path="" LayerStatus="ReadWrite" />
</Layers>
</Project>');
foreach($xml->ProjectInformation->Details->attributes() as $key => $value)
{
echo "$key : $value ";
}
foreach($xml->ProjectInformation->ProjectBounds->attributes() as $key => $value)
{
echo "$key : $value ";
}
As a more generic answer, you can use :
foreach($xml->ProjectInformation->children() as $child)
{
foreach($child->attributes() as $key => $value)
{
echo "$key : $value ";
}
}
You can also use xpath, as said in a comment.
Try with this.
$x = $xmlDoc->getElementsByTagName('ProjectInformation');
foreach ($x->childNodes as $nodename) {
if( $nodename->nodeName == 'FileHeader' ){
echo $nodename->nodeName. " - " . $nodename->nodeValue."<br>";
}
}
Where $nodename->nodeName holds all the child node names like FileHeader, Details, etc.
I have the following xml document:
<?xml version="1.0"?>
<root>
<offers count="3009">
<offer>
<offerId>25</offerId>
<offer_type>for sale</offer_type>
<offer_status>available</offer_status>
<building_floors></building_floors>
<title>title</title>
<photos count="4">
<photo zIndex="1">1.jpg</photo>
<photo zIndex="2">2.jpg</photo>
<photo zIndex="3">3.jpg</photo>
<photo zIndex="4">4.jpg</photo>
</photos>
</offer>
</offers>
</root>
I am using this php code to get results from the xml:
$xml = simplexml_load_file("offers.xml")
or die("Error: Cannot create object");
foreach($xml->children() as $offers){
foreach($offers->children() as $offer => $data){
echo $data->offerId;echo "<br />";//and so on for each element
foreach ($xml->offers->offer->photos->photo as $aaa){
$photos=$aaa; echo "<br />";
//echo $xml;
$photo = explode("<br /> ", $photos);
foreach($photo as $value) echo $value; echo '<br />';//echo $value
}
}
}
When I try to loop the photo element I get all photos but only for the first offer.
My question is what I am doing wrong and why I do not get photos for each offer?
The problem is with the way you retrieve the photo elements. You start from the root element so it always give you the same node.
You should use $data like this :
foreach ($data->photos->photo as $aaa){
cleaning a bit your code you should use this to display the photo elements:
$xml = simplexml_load_file("offers.xml") or die("Error: Cannot create object");
foreach($xml->children() as $offers){
foreach($offers->children() as $offer){
echo "Offer id : " . $offer->offerId . "<br>";
foreach ($offer->photos->photo as $photo){
$val = (string) $photo;
echo $val . "<br>";
}
}
}