Getting XML attribute from the inner node using PHP SimpleXML is failing - php

Chaps,
I am trying to get attributes of the 'file' node in the following XML with SimpleXml but every time is gives me back null. I have successfully got the attributes for the study node but fail to get the 'file' atts .
here is the xml :
<?xml version="1.0" encoding="UTF-8"?>
<studies>
<study uid="1.3.12.2" acc="181">
<date>20051218</date>
<time>2156</time>
<ref>CG</ref>
<desc>Abdomen</desc>
<id></id>
<path>S00001</path>
<modality>CR</modality>
<reports>
<file cat="UNK" date="20141124">Card_Cloud.txt</file>
</reports>
</study>
and here is my code :
$studyXML = new SimpleXMLElement($studyXML);
$studyXML_array = array();
foreach ($studyXML ->study as $study)
{
// Getting uid and accession from XML attributes
$uid = (!empty($study)) ? (String)$study->attributes()->uid : '';
$acc = (!empty($study)) ? (String)$study->attributes()->acc : '';
// Getting the reports and putting them in an array
$reports = array ();
foreach($study->reports as $rep)
{
$cat = (String)$rep->attributes()->cat;
$reports[] = (String)$rep->file;
}
// Constructing the xml as an array
$studyXML_array[] = array
(
'uid' => $uid,
'acc' => $acc,
'date' => (String)$study->date,
'reports' => $reports
);
}
I can get "uid" and "acc" but I can't get "cat" and "date" inside file node.
When I look at the array of the xml in my debug variables I can see uid and acc attributes but no sign of cat and date attributes.
I Would really appreciate any help.
I prefer to stick to SimpleXML as all my code is using that so far.
Cheers

This is how I did it based on Ghost answer.
$reports = array ();
foreach($study->reports->file as $rep)
{
$temp = array();
$temp['repName'] = (String)$rep;
// Getting cat and date attributes of the report
foreach($rep->attributes() as $key => $rep)
{
$temp[$key] = (string) $rep;
}
$reports[] = $temp;
}

If you're trying to use print_r()/var_dump() to check, then it will do no justice. But it is there, try to traverse to it along with using ->attributes() inside the foreach as well:
$studyXML = new SimpleXMLElement($studyXML);
$studyXML_array = array();
foreach ($studyXML ->study as $study)
{
// Getting uid and accession from XML attributes
$uid = (!empty($study)) ? (String)$study->attributes()->uid : '';
$acc = (!empty($study)) ? (String)$study->attributes()->acc : '';
// Getting the reports and putting them in an array
$reports = array();
// loop each attribute
foreach($study->reports->file->attributes() as $key => $rep)
{
$reports[$key] = (string) $rep;
}
// Constructing the xml as an array
$studyXML_array[] = array(
'uid' => $uid,
'acc' => $acc,
'date' => (String) $study->date,
'reports' => $reports
);
}
echo '<pre>';
print_r($studyXML_array);
Sample Output:
Array
(
[0] => Array
(
[uid] => 1.3.12.2
[acc] => 181
[date] => 20051218
[reports] => Array
(
[cat] => UNK
[date] => 20141124
)
)
)

Related

Array return, enumerat or other solution?

I'm having trouble identifying each row of this array ... would it be possible to enumerate or otherwise be able to pull a specific array field?
My code is:
<?php
/*
Generic function to fetch all input tags (name and value) on a page
Useful when writing automatic login bots/scrapers
*/
function get_input_tags($html)
{
$post_data = array();
// a new dom object
$dom = new DomDocument;
//load the html into the object
$dom->loadHTML($html);
//discard white space
$dom->preserveWhiteSpace = false;
//all input tags as a list
$input_tags = $dom->getElementsByTagName('input');
//get all rows from the table
for ($i = 0; $i < $input_tags->length; $i++)
{
if( is_object($input_tags->item($i)) )
{
$name = $value = '';
$name_o = $input_tags->item($i)->attributes->getNamedItem('name');
if(is_object($name_o))
{
$name = $name_o->value;
$value_o = $input_tags->item($i)->attributes->getNamedItem('value');
if(is_object($value_o))
{
$value = $input_tags->item($i)->attributes->getNamedItem('value')->value;
}
$post_data[$name] = $value;
}
}
}
return $post_data;
}
/*
Usage
*/
error_reporting(~E_WARNING);
$html = file_get_contents("https://secure.donman.net.au/client/ozchild/Donate.aspx");
echo "<pre>";
print_r(get_input_tags($html));
echo "</pre>";
?>
Generate the result
[radInMemDiscloseAmount] => No
[txtInMemOfAddress] =>
[txtInMemOfSuburb] =>
[txtInMemOfState] =>
[txtInMemOfPostCode] =>
[txtInHonorOfName] =>
[txtInHonorOfAddress] =>
[txtInHonorOfSuburb] =>
[txtInHonorOfState] =>
[txtInHonorOfPostCode] =>
[HonorEventType] => gf_other_choice
[HonorEventTypeOtherText] => Other
how can I have something like this?
[0][radInMemDiscloseAmount] => No
[1][txtInMemOfAddress] =>
[2][txtInMemOfSuburb] =>
[3][txtInMemOfState] =>
[4][txtInMemOfPostCode] =>
[5][txtInHonorOfName] =>
[6][txtInHonorOfAddress] =>
[7][txtInHonorOfSuburb] =>
[8][txtInHonorOfState] =>
[9][txtInHonorOfPostCode] =>
[10][HonorEventType] => gf_other_choice
[11][HonorEventTypeOtherText] => Other
how can I have something like this? or some way to identify array rows?
I'm having trouble identifying each row of this array ... would it be possible to enumerate or otherwise be able to pull a specific array field?

Parsing multi nested child in XML in PHP

Firstly first I am a beginner with PHP. Especially when i have to deal with XML Parsing , I am having a struggle with it right now, lots of xml. Hours and hours already I tried solving it and its already giving me a headache.
Here the XML :
<v1:product>
<v1:data>
<v1:account_id>5637</v1:account_id>
<v1:account_name>John Doe</v1:account_name>
<v1:product_id>f4dc8300-1f13-11e8-bfa43d4d9ee60f6b</v1:product_id>
<v1:product_name>Product Test</v1:product_name>
<v1:product_desc>
<v1:name>Arc</v1:name>
<v1:unit>boxes</v1:unit>
<v1:value>10</v1:value>
</v1:product_desc>
<v1:product_desc>
<v1:name>Birg</v1:name>
<v1:unit>kilos</v1:unit>
<v1:value>2</v1:value>
</v1:product_desc>
<v1:product_desc>
<v1:name>Cyitha</v1:name>
<v1:unit>Minutes</v1:unit>
<v1:value>30</v1:value>
</v1:product_desc>
<v1:offer>
<v1:offer_id>3575374</v1:offer_id>
<v1:offer_name>Flash</v1:offer_name>
</v1:offer>
</v1:data>
<v1:data>
<v1:account_id>5892</v1:account_id>
<v1:account_name>John Doe</v1:account_name>
<v1:product_id>jsad2sdx-asd2-983j</v1:product_id>
<v1:product_name>Product Test 2</v1:product_name>
<v1:product_desc>
<v1:name>Arc</v1:name>
<v1:unit>boxes</v1:unit>
<v1:value>2</v1:value>
</v1:product_desc>
<v1:product_desc>
<v1:name>Birg</v1:name>
<v1:unit>kilos</v1:unit>
<v1:value>10</v1:value>
</v1:product_desc>
<v1:product_desc>
<v1:name>Cyitha</v1:name>
<v1:unit>Minutes</v1:unit>
<v1:value>99</v1:value>
</v1:product_desc>
<v1:offer>
<v1:offer_id>3575374</v1:offer_id>
<v1:offer_name>Flash</v1:offer_name>
</v1:offer>
</v1:data>
</v1:product>
and this is what i have in PHP
$objGetEmAll = new DOMDocument();
$objGetEmAll->loadXML($theXML);
$datas = $objGetEmAll->getElementsByTagName('data');
$responseValue = array();
foreach($datas as $data) //each element of DATA
{
$dataValue = array();
if($data->childNodes->length)
{
foreach($data->childNodes as $i)
{
$dataValue[$i->nodeName] = $i->nodeValue;
}
}
$responseValue[] = $dataValue;
}
but still fail when i want to extract value dynamically inside product_desc tag. I want to change XML above into an array which is like below
Array
(
[0] => Array
(
[v1:account_id] => 5637
[v1:account_name] => adsfafds
[v1:product_id] => 124asd
[v1:product_name] => HALO
[v1:product_desc] => Array
(
[0] => Array
(
[v1:name] => A
[v1:unit] => BOXes
[v1:value] => 7
)
[1] => Array
(
[v1:name] => B
[v1:unit] => mins
[v1:value] => 1000
)
[2] => Array
(
[v1:name] => C
[v1:unit] => call
[v1:value] => 700
)
[3] => Array
(
[v1:name] => D
[v1:unit] => GB
[v1:value] => 4
)
)
[v1:offer] => Array
(
[v1:offer_id] => 3575374
[v1:offer_name] => Flash
)
)
)
I know maybe this is the easy one, but for me who just joined programming in these last month, this is confusing. Links or helps are welcome
Use this
$objGetEmAll = new DOMDocument();
$objGetEmAll->loadXML($theXML);
$datas = $objGetEmAll->getElementsByTagName('data');
$responseValue = array();
foreach($datas as $data) //each element of DATA
{
$dataValue = array();
$product_desc_counter = 0;
$offer_counter = 0;
if($data->childNodes->length)
{
foreach($data->childNodes as $i) {
// for v1:product_desc group case :1
if($i->nodeName == 'v1:product_desc' ){
foreach($i->childNodes as $p) {
$dataValue[$i->nodeName][ $product_desc_counter][$p->nodeName] = $p->nodeValue;
}
$product_desc_counter ++;
} else if($i->nodeName == 'v1:offer' ) // for offer group case:2
{
foreach($i->childNodes as $p) {
$dataValue[$i->nodeName][ $offer_counter][$p->nodeName] = $p->nodeValue;
}
$offer_counter ++;
}
else // case:3
$dataValue[$i->nodeName] = $i->nodeValue;
}
}
$responseValue[] = $dataValue;
}
In the above lines we loop over all data nodes then check if it has any nodes if it doesn't( like for items account_name, product_id ..) we simply store it's nodeValue in our result array ie. in $responseValue. If it has any child (v1:product_desc,v1:offer ie case:1 or 2) we again loop over its children and append them to combination of corresponding key and the corresponding loop counter ( $product_desc_counter or $offer_counter ) .It might be hard at first to understand (specially array indexes) but after fiddling with it for a while you will grasp it.

Save array to XML file using SimpleXML

I'm using the code below to sort the content of my XML file by "WebCategory". My question is how do I save the newly sorted $products array back to the XML file?
<?php
$products = array();
$xml = simplexml_load_file('nwgalaxy-edited.xml');
foreach($xml->Product as $item) {
$products[] = array(
'ProductID' => (string)$item->attributes()->ProductID,
'Description' => (string)$item->Description,
'WebCategory' => (string)$item->WebCategory,
'WebSubCategory' => (string)$item->WebSubCategory,
'WebSubCat2' => (string)$item->WebSubCat2,
'QtyOnHand' => intval($item->QtyOnHand),
'SellingPrice' => intval($item->SellingPrice),
'ListPrice' => intval($item->ListPrice),
'NWGalaxy' => intval($item->NWGalaxy),
'UPC' => intval($item->UPC),
'VendorProductID' => (string)$item->VendorProductID,
'ImageSmall' => (string)$item->ImageSmall,
'ImageLarge' => (string)$item->ImageLarge
);
}
array_sort_by_column($products, 'WebCategory');
function array_sort_by_column(&$array, $column, $direction = SORT_ASC) {
$reference_array = array();
foreach($array as $key => $row) {
$reference_array[$key] = $row[$column];
}
array_multisort($reference_array, $direction, $array);
}
?>
This may work, not tested but should give general idea.
// Create tag products
$xml = new SimpleXMLElement('<products/>');
// Walk the array with callback to method $xml->addChild($this)
array_walk_recursive($products, array($xml, 'addChild'));
// Save generated content to file.
file_put_contents('nwgalaxy-edited.xml', $xml->asXML());

Get value from XML Array in PHP

I'm trying to get 1 value from my XML Array.
This is the code:
<?php
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;
}
?>
Result:
<?php
$xmlUrl = "http://radiourl:port/status.xsl"; // XML feed file/URL
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
?>
The result of print_r($arrXml); is this:
Array (
[Mount-Point] => /listen.mp3
[Stream-Title] => VibboStream
[Stream-Description] => name
[Content-Type] => audio/mpeg
[Mount-started] => 14/Jun/2016:04:28:49 -0500
[Bitrate] => 128
[Current-Listeners] => 1
[Peak-Listeners] => 3
[Stream-Genre] => Various
[Stream-URL] => http://url [ice-bitrate] => 128
[icy-info] => ice-samplerate=44100;ice-bitrate=128;ice-channels=2
[Current-Song] => Artist - Title
)
So what I'm trying to get is the part [Current-Song] => Artist - Title.
When I echo it I'd like to only see Artist - Title
Can someone help me with this?
You already have the xml object. Just use it.
$artistTitle = $xmlObj->{'Current-Song'};
And just use it from there.
More info on that curly brace syntax here

PHP array to XML with attributes

In CakePHP I know the XML-class in cake.libs. What I like on this easy to use class is the fact that you can convert an array to xml with attributes.
On a current project I'm working with Zend Framework and I am missing this nice class.
Does anybody know how I can convert an PHP-array to XML with attributes easily?
I tried this one but unfortunately its not easy to handle result arrays from database cause you have to define the attributes inside the array.
Maybe I have missed something in ZF? Or does anybody know how to adapt the CakePHP class to ZF?
Many thanks for any helpful hints.
This function will allow you to create XML document with simple PHP array variable. Nodes are just stacked onto each other and naming it 'Attribute_XXX' will add atribute XXX to that parent node.
function to_xml(SimpleXMLElement $object, array $data)
{
$attr = "Attribute_";
foreach ($data as $key => $value) {
if (is_array($value)) {
$new_object = $object->addChild($key);
to_xml($new_object, $value);
} else {
if(strpos($key, $attr) !== false){
$object->addAttribute(substr($key, strlen($attr)), $value);
}else{
$object->addChild($key, $value);
}
}
}
}
Usage:
$my_array = array (
'TagN1' => array (
'TagInsideOfIt' => array (
'Atrribute_IDuser' => 'anything',
'RegularTag' => 'whatever',
'Address' => array(
'Attribute_ID' => '111',
'Attribute_key' => 'aaa',
'Company' => 'Google Inc.'
)
)
)
);
$xml = new SimpleXMLElement('<root/>');
to_xml($xml, $my_array);
Header('Content-type: text/xml');
print($xml->asXML());
You can get some answers at this URL How to convert array to SimpleXML
An alternative/fast and easy approach would be to convert array data into JSON, that would be faster as well using Zend library. Converting array into JSON is very easy as using follows functions.
Zend_Json::encode() and Zend_Json_Encoder::encode()
Tanks, a using the code of #jezda159 and i modified for me, this is my code:
the array:
$elements_array = array(
"node" => array(
"subnode" => array(
"[attribute]" => "valueOfAttribute",
"[second-attribute]" => "valueOfAttribute",
"second-subnode" => array(
"[attribute]" => "valueOfAttribute",
"[second-attribute]" => "valueOfAttribute",
),
"ListOfElements" => array(
"one",
"two",
"tree"
)
)
),
);
The code:
function array_to_xml($data, $object){
foreach ($data as $key => $value) {
$keyname = is_numeric( $key ) ? "item".$key : $key;
if (is_array($value)) {
$new_object = $object->addChild($keyname);
array_to_xml($value, $new_object);
} else {
preg_match("#\[([a-z0-9-_]+)\]#i", $keyname, $attr);
if( count($attr) ){
$object->addAttribute($attr[1], $value);
}else{
$object->addChild($keyname, $value);
}
}
}
}
$xml_user_info = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><Elements></Elements>');
//function call to convert array to xml
array_to_xml($elements_array,$xml_user_info);
header('Content-type: text/xml');
//show generated xml file
echo $xml_user_info->asXML();
The result:
<?xml version="1.0" encoding="UTF-8"?>
<Elements>
<node>
<subnode attribute="valueOfAttribute" second-attribute="valueOfAttribute">
<second-subnode attribute="valueOfAttribute" second-attribute="valueOfAttribute"/>
<ListOfElements>
<item0>one</item0>
<item1>two</item1>
<item2>tree</item2>
</ListOfElements>
</subnode>
</node>
</Elements>

Categories