PHP XML losing attributes - php

i have a problem while I load xml string into SimpleXMLElement ( i tried also with DOCDocument but result is the same). In XML i have this :
<definedNames>
<definedName name="name1" Id="1" hidden="1">NAME_TEST</definedName>
<definedName name="name2" Id="4" hidden="1">NAME_TEST_2</definedName>
</definedNames>
Now i need access to specific tag using 'name' attribute. But always when i tried to print_r, var_dump or smth else i always see all other attributes, but when comes to i see only array with
[0] = > NAME_TEST,
[1] => NAME_TEST_2
I tried also xpath, but everytime when i refer to attributes inside i get empty array.
So for now i tried : xpath, SimpleXMLDom, DOCDocument but result is always the same - empty array. Any clue ?
#edit
$xl->LoadTemplate('#xl/workbook.xml');
if (isset($workbook) && is_array($workbook) && count($workbook > 0)) {
$dom = new DOMDocument();
$dom->loadXML($xl->Source);
$xpath = new DOMXpath($dom);
foreach ($xpath->evaluate('//definedName') as $definedName) {
echo $definedName->getAttribute('name');
}
} else {
$TBS->Source = preg_replace('~\<definedNames\>.*\<\/definedNames\>~', '', $TBS->Source);
}
#edit2 - xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">
<definedNames>
<definedName name="name1" Id="1" hidden="1">NAME_TEST</definedName>
<definedName name="name2" Id="4" hidden="1">NAME_TEST_2</definedName>
</definedNames>
</workbook>
i know there is smth like , but i already tried :
$xpath->evaluate('//workbook/definedNames/definedName[#*]')
or
$xpath->evaluate('/workbook/definedNames/definedName[#name="name1"]')
still result is empty.

With DOMDocument, you use Xpath to fetch values or nodes.
Load the XML into a document and create an DOMXpath instance for it:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
Fetch a node value as string:
var_dump($xpath->evaluate('string(//definedName[#name="name1"])'));
Output:
string(9) "NAME_TEST"
Fetch all definedName element data into an array:
$byName = [];
foreach ($xpath->evaluate('//definedName') as $definedName) {
$byName[] = [
'name' => $definedName->getAttribute('name'),
'id' => $definedName->getAttribute('Id'),
'hidden' => $definedName->getAttribute('hidden'),
'text' => $definedName->nodeValue
];
}
var_dump($byName);
Output:
array(2) {
[0]=>
array(4) {
["name"]=>
string(5) "name1"
["id"]=>
string(1) "1"
["hidden"]=>
string(1) "1"
["text"]=>
string(9) "NAME_TEST"
}
[1]=>
array(4) {
["name"]=>
string(5) "name2"
["id"]=>
string(1) "4"
["hidden"]=>
string(1) "1"
["text"]=>
string(11) "NAME_TEST_2"
}
}

You can use the attributes() method on each element of the SimpleXMLElement Object. You can then access them:
$xml = '<definedNames>
<definedName name="name1" Id="1" hidden="1">NAME_TEST</definedName>
<definedName name="name2" Id="4" hidden="1">NAME_TEST_2</definedName>
</definedNames>';
$x = new SimpleXMLElement($xml);
foreach ($x as $element) {
var_dump($element->attributes());
}
The above returns:
object(SimpleXMLElement)#4 (1) {
["#attributes"]=>
array(3) {
["name"]=>
string(5) "name1"
["Id"]=>
string(1) "1"
["hidden"]=>
string(1) "1"
}
}
object(SimpleXMLElement)#3 (1) {
["#attributes"]=>
array(3) {
["name"]=>
string(5) "name2"
["Id"]=>
string(1) "4"
["hidden"]=>
string(1) "1"
}
}
You can then access individual attributes by using in the loop:
foreach ($x as $element) {
$element->attributes()->hidden;
$element->attributes()->Id;
$element->attributes()->name;
}

try simplexml_load_string()
$p = '<definedNames>
<definedName name="name1" Id="1" hidden="1">NAME_TEST</definedName>
<definedName name="name2" Id="4" hidden="1">NAME_TEST_2</definedName>
</definedNames>';
$xml = simplexml_load_string($p);
echo $xml->definedName[0]->attributes()->name;
echo $xml->definedName[1]->attributes()->name;
or use foreach to get all attaributes

Related

Removing link from Unordered list as string in array

Using PHP, I would like to remove all the links in an unordered list and put them in an array. So the output would be: array[0]='Benefits', array[1]='Cost Savings', etc.
<ul>
<li>Benefits</li>
<li>Cost Savings</li>
<li>Member listing</li>
</ul>
Using; preg_match_all('/<a href=\"(.*?)\"[.*]?>(.*?)<\/a>/i', $content, $matches);
I get:
array(3) { [0]=> array(3) { [0]=> string(24) "Benefits" [1]=> string(28) "Cost Savings" [2]=> string(30) "Member listing" } [1]=> array(3) { [0]=> string(1) "#" [1]=> string(1) "#" [2]=> string(1) "#" } [2]=> array(3) { [0]=> string(8) "Benefits" [1]=> string(12) "Cost Savings" [2]=> string(14) "Member listing" } }
But i need to put it into one array.
To fetch the links you can leverage domdocument and domxpath
$html = '<html><body><ul>
<li>Benefits</li>
<li>Cost Savings</li>
<li>Member listing</li>
</ul></body></html>';
$dom = new DOMDocument();
$dom->loadHTML( $html ); // loads the html into the class
$xpath = new DOMXPath( $dom );
$items = $xpath->query('*/ul/li/a'); // matches any elements in this order
$array = array();
foreach( $items as $item )
{
$array[] = $dom->saveHTML( $item ); // using the parent document, get just a single elements html
}
// Array
// (
// [0] => Benefits
// [1] => Cost Savings
// [2] => Member listing
// )

Empty key converts into array in multidimentional array in php?

I am uploading one xml and trying to convert that data into php array and have to store it in db. My problem is when i get empty key inside loop it automatically converts into array. but i want it as a string only. As i am getting array so its difficult me to store it in db.Please help me with the solution.
Current Output :
array(19) {
["EMP_NAME"]=>
string(12) "ABC"
["EMP_ADDRESS"]=>
string(1) "MUMBAI"
["DEPARTMENT"]=>
string(1) "IT"
["LOCATION"]=>
array(0) {
}
}
Expected Output :
array(19) {
["EMP_NAME"]=>
string(12) "ABC"
["EMP_ADDRESS"]=>
string(1) "MUMBAI"
["DEPARTMENT"]=>
string(1) "IT"
["LOCATION"]=>
string(1) ""
}
This is my php code to get data from xml and looping through array.
$xml = file_get_contents('uploads/data.xml');
$xml = simplexml_load_string($xml);
$xml_array = json_decode(json_encode((array) $xml), 1);
$data = ($xml_array);
foreach($data as $val){
//var_dump($val);
}
I tried to fix it after getting.
<?php
function fixContent(&$val, $key = null) {
if (is_array($val)) {
if (!$val) $val = '';
else fix($val);
}
}
function fix(&$arr) {
array_walk($arr, 'fixContent');
array_walk_recursive($arr, 'fixContent');
}
$xml = "<?xml version='1.0'?>
<document>
<title>Forty What?</title>
<from>Joe</from>
<to>Jane</to>
<body></body>
</document>";
$xml = simplexml_load_string($xml);
$xml_array = json_decode(json_encode((array) $xml), 1);
fix($xml_array);
$data = $xml_array;
var_dump($data);
?>
Output:
array(4) {
["title"]=>
string(11) "Forty What?"
["from"]=>
string(3) "Joe"
["to"]=>
string(4) "Jane"
["body"]=>
string(0) ""
}
Demo: https://paiza.io/projects/qQC5pfvhGz_FniCIK6S_9g
Generic conversions are often not the best solution. They allow the source to control the output - especially if you use debug features like serializing a SimpleXMLElement instance.
Read the data from XML and add it to a result. This puts your code in control of the output. You can change the keys, validate and convert values, add defaults, ...
$xml = <<<'XML'
<EMP>
<EMP_NAME>ABC</EMP_NAME>
<EMP_ADDRESS>MUMBAI</EMP_ADDRESS>
<DEPARTMENT>IT</DEPARTMENT>
<LOCATION></LOCATION>
</EMP>
XML;
$employee = new SimpleXMLElement($xml);
$result = [
'EMP_NAME' => (string)$employee->EMP_NAME,
'EMP_ADDRESS' => (string)$employee->EMP_ADDRESS,
'DEPARTMENT' => (string)$employee->DEPARTMENT,
'LOCATION' => (string)$employee->LOCATION
];
var_dump($result);
Output:
array(4) {
["EMP_NAME"]=>
string(3) "ABC"
["EMP_ADDRESS"]=>
string(6) "MUMBAI"
["DEPARTMENT"]=>
string(2) "IT"
["LOCATION"]=>
string(0) ""
}
Or with DOM:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$result = [
'EMP_NAME' => $xpath->evaluate('string(/EMP/EMP_NAME)'),
'EMP_ADDRESS' => $xpath->evaluate('string(/EMP/EMP_ADDRESS)'),
'DEPARTMENT' => $xpath->evaluate('string(/EMP/DEPARTMENT)'),
'LOCATION' => $xpath->evaluate('string(/EMP/LOCATION)')
];
var_dump($result);

Convert XML file to an array

I try to convert XML file to an array in PHP. However, when reading the first array, it is not in form of key and value array.
Is there any way to convert the first data in form of Key and Value? Thanks in advance.
readXML.php
function convertXMLFileToArray()
{
$xml_file = 'customers.xml';
$array_name = 'customer';
//Check whether the file exist
if(file_exists($xml_file)){
//Read the data from xml file
$dt = simplexml_load_file($xml_file,null,LIBXML_NOCDATA);
$json = json_encode($dt);
$outer_array = json_decode($json,TRUE);
//Remove outer array
$array = $outer_array[$array_name];
}
else{
$array = null;
}
var_dump($array);
return $array;
}
Case1
customers.xml
<customers>
<customer>
<cid>1</cid>
<name>Adam</name>
<age>20</age>
</customer>
</customers>
Output
array(3) { ["cid"]=> string(1) "1" ["name"]=> string(4) "Adam" ["age"]=> string(2) "20"}
Case2
customers.xml
<customers>
<customer>
<cid>1</cid>
<name>Adam</name>
<age>20</age>
</customer>
<customer>
<cid>2</cid>
<name>David</name>
<age>23</age>
</customer>
</customers>
Output
array(2) {
[0]=> array(3) { ["cid"]=> string(1) "1" ["name"]=> string(4) "Adam"
["age"]=> string(2) "20" }
[1]=> array(3) { ["cid"]=> string(1) "2" ["name"]=> string(4) "David"
["age"]=> string(2) "23" }
}
Here's one option (using simplexml_load_string instead of file):
function getCustomersFromXml($xml, $key = 'customer')
{
$data = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$out = [];
foreach ($data->$key as $item) {
$out[] = (array) $item;
}
return $out;
}
So you load the XML data, loop the customers object and push each customer object cast as an array into your output.
https://eval.in/990764

xpath not return values

I am able to pull the necessary information using xpath, when I use var_dump using the following code. When I try to add a foreach loop to return all ["href"] values i get a blank page any ideas where I am messing up?
$dom = new DOMDocument();
#$dom->loadHTML($source);
$xml = simplexml_import_dom($dom);
$rss = $xml->xpath("/html/body//a[#class='highzoom1']");
$links = $rss->href;
foreach ($links as $link){
echo $link;
}
Here is the array of information.
array(96) {
[0]=>
object(SimpleXMLElement)#3 (2) {
["#attributes"]=>
array(2) {
["href"]=>
string(49) "/p/18351/test1.html"
["class"]=>
string(10) "highzoom1"
}
[0]=>
string(36) ""test1"
}
[1]=>
object(SimpleXMLElement)#4 (2) {
["#attributes"]=>
array(2) {
["href"]=>
string(43) "/p/18351/test2.html"
["class"]=>
string(10) "highzoom1"
}
[0]=>
string(30) ""test2"
}
[2]=>
object(SimpleXMLElement)#5 (2) {
["#attributes"]=>
array(2) {
["href"]=>
string(48) "/p/18351/test3.html"
["class"]=>
string(10) "highzoom1"
}
[0]=>
string(35) ""test3"
}
Instead of:
$rss = $xml->xpath("/html/body//a[#class='highzoom1']");
use:
$hrefs = $xml->xpath("/html/body//a[#class='highzoom1']/#href");
The original XPath expression (the first above) you are using selects any a element in the XML document the value of whose class atribute is 'highzoom1' and that (the a element) is a descendent of a body that is a child of the top element (named html) in the XML document.
However, you want to select the href attributes of these a elements -- not the a elements themselves.
The second XPath expression above select exactly the href attributes of these a elements.
$links = $rss->href;
will never work, as $rss is a DOMNodeList object, and won't have an href attribute. Instead, you'd want to do this:
$rss = $xml->xpath("/html/body//a[#class='highzoom1']");
foreach($rss as $link) {
echo $link->href;
}
Or you can address $rss as an array directly:
echo $rss[5]->href; // echo out the href of the 6th link found.

Why does is_array() return false?

I have this SimpleXML object:
object(SimpleXMLElement)#176 (1) {
["record"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#39 (2) {
["f"]=>
array(2) {
[0]=>
string(13) "stuff"
[1]=>
string(1) "1"
}
}
[1]=>
object(SimpleXMLElement)#37 (2) {
["f"]=>
array(2) {
[0]=>
string(13) "more stuff"
[1]=>
string(3) "90"
}
}
}
Why does is_array($object->record) return false? It clearly says it's an array. Why can't I detect it using is_array?
Also, I am unable to cast it as an array using (array) $object->record. I get this error:
Warning: It is not yet possible to
assign complex types to properties
SimpleXML nodes are objects that can contain other SimpleXML nodes. Use iterator_to_array().
It's not an array. The var_dump output is misleading. Consider:
<?php
$string = <<<XML
<?xml version='1.0'?>
<foo>
<bar>a</bar>
<bar>b</bar>
</foo>
XML;
$xml = simplexml_load_string($string);
var_dump($xml);
var_dump($xml->bar);
?>
Output:
object(SimpleXMLElement)#1 (1) {
["bar"]=>
array(2) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
}
}
object(SimpleXMLElement)#2 (1) {
[0]=>
string(1) "a"
}
As you can see by the second var_dump, it is actually a SimpleXMLElement.
I solved the problem using count() function:
if( count( $xml ) > 1 ) {
// $xml is an array...
}

Categories