I've created a simple XML document that will hold information on numerous cities.
<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
<city>
<id>London</id>
</city>
<city>
<id>New York</id>
</city>
</config>
I'm trying to extract the city elements and place them into an array. I have the following so far and the output is simply Array when I call the function.
<?php
$configFile = 'cityConfig.xml';
function getCityConfig($configFile) {
$xml = new SimpleXmlElement(file_get_contents("cityConfig.xml"));
$cities = array();
$cityId = $xml->city[0]->id;
array_push($cities, $cityId);
$cityId = $xml->city[1]->id;
array_push($cities, $cityId);
//var_dump($cities);
return $cities;
}
//print_r(getCityConfig($configFile));
echo getCityConfig($configFile);
?>
var_dump suggests that values are being added into the array.
array(2) { [0]=> object(SimpleXMLElement)#2 (1) { [0]=> string(6) "London" } [1]=> object(SimpleXMLElement)#4 (1) { [0]=> string(8) "New York" } } Array
I'm trying to achieve something along these lines.
$cities = array(
'London',
'New York',
'Paris'
);
The array indexes are called in my index.php to display content.
$pageIntroductionContent = 'The following page brings twin cities together. Here you will find background information on ' . $cities[0] . ', ' . $cities[1] . ' and ' . $cities[2] . '.';
Any ideas where I'm going wrong?
Thanks in advance.
The fact is that in SimpleXMLElement object, all the data is represented as an object, including attributes (as your var_dump suggests, in fact). So, you can get strings by casting these object, because they implement a _toString() method I think. Try:
$cityId = (string) $xml->city[0]->id;
It should work.
Related
I have an XML page called (www.example.com/name.xml)
it contains the bellow elements :
<xml>
<names>
<name id='6' >Name 1 </name>
<name id='7'>Name 2</name>
<name id='8'>Name 3</name>
</names>
</xml>
and here is my PHP script :
<?php
$id='6';
$url = "www.example.come/name.xml";
$xml = simplexml_load_file($url);
$position ="$xml->name id='$id' ";
?>
So how can I get it ?
You can simply use xpath for this:
$id='6';
$xml = simplexml_load_file($url);
$position = (string)$xml->xpath("//name[#id='$id']")[0];
echo $position;
Output:
Name 1
This uses xpath to get the text from the <name> where id is 6. Then it casts the SimpleXMLElement to (string), thus providing the output.
Based on your provided data, you could do it like this:
$id='6';
foreach($xml->names->name as $name) {
if ((string)$name->attributes()->id === $id) {
// here $name will be the element for which the attribute id='6'
var_dump($name);
}
}
Will result in:
object(SimpleXMLElement)#3 (2) {
["#attributes"]=>
array(1) {
["id"]=>
string(1) "6"
}
[0]=>
string(7) "Name 1 "
}
$name is of type SimpleXMLElement and the value you are looking for is in the attributes.
I need som help reading a XML that has namespaces.
I can read file with out any namepaces but not with namespaces..
XML sample:
<?xml version="1.0" encoding="utf-8"?>
<OrderResponse xmlns:cac="urn:basic:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:xsi="http://www.w3.org/" xmlns:cbc="urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2" xmlns="urn:basic:names:specification:ubl:schema:xsd:OrderResponse-2">
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:AccountingCostCode>TESTER TEST</cbc:AccountingCostCode>
<cac:OrderReference>
<cbc:ID>100067010</cbc:ID>
<cbc:IssueDate>2016-06-15</cbc:IssueDate>
<cbc:OrderTypeCode>EDI</cbc:OrderTypeCode>
</cac:OrderReference>
</OrderResponse>
I need to get the value of the ..
Im trying do it with DomDocument.
Here is my code:
function SearchXMLID($xml){
var_dump($xml);
$doc = new DOMDocument();
$doc->load($xml);
$id = $doc->getElementsByTagNameNS('urn:basic:names:specification:ubl:schema:xsd:CommonAggregateComponents-2','cbc:ID');
foreach($id as $i){
echo "<pre>";var_dump('NS',$i->nodeValue,PHP_EOL);"</pre>";
}
}
$files = glob('dataXMl/*xml');
echo "<pre>";var_dump($files,PHP_EOL);"</pre>";
foreach($files as $f){
SearchXMLID($f);
}
This code works but is getting all namespaces with 'cbc:' and stores the in a string..
array(1) {
[0]=>
string(17) "dataXMl/test1.xml"
}
string(1) "
"
string(17) "dataXMl/test1.xml"
string(2) "NS"
string(40) "
100000050
2016-06-15
EDI
"
string(1) "
"
It gets all tags with the namespace 'cbc'.. but i want to get the tag 'cbc:ID' only.
What am i doing wrong?
I'm no expert with php coding but my gut tells me that both of your parameters for getElementsByTagNameNS are wrong.
Try this:
$id = $doc->getElementsByTagNameNS('urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2','ID');
i.e. use the correct namespace-uri: "urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2"
and drop the cbc prefix
How can I convert XML to an array that I can iterate over.
Here is the example of my XML
<user>
<student>yes</student>
<id>1</id>
<name>John</name>
</user>
<user>
<student>yes</student>
<id>1</id>
<name>Billy</name>
</user>
My php looks like this
$tmpTemplates = new XDomDocument();
$tmpTemplates->load('.....myFile.xml');
$xPath = new DomXPath($tmpTemplates);
$query = "//user[student='yes']";
$tmpTemplate = $xPath->query($query);
What I want to be able to do is
foreach($tmpTemplate as $tt){
var_dump($tt->student);
var_dump($tt->id);
var_dump($tt->name);
}
Now I'm only able to print out nodeValue which gives me something like this:
yes
1
John
How can I make it an array or an object so I can apprach each value by its key?
You used the same id for both records in your example, so I changed the id of the first one and added a document element.
<users>
<user>
<student>yes</student>
<id>2</id>
<name>John</name>
</user>
<user>
<student>yes</student>
<id>1</id>
<name>Billy</name>
</user>
</users>
Use DOMXpath:evaluate() to fetch the details, the second argument is the context node for the expression.
$document = new DOMDocument();
$document->loadXml($xmlString);
$xPath = new DomXPath($document);
$students = [];
foreach ($xPath->evaluate("//user[student='yes']") as $student) {
$id = $xPath->evaluate('string(id)', $student);
$students[$id] = [
'id' => $id,
'name' => $xPath->evaluate('string(name)', $student)
];
}
var_dump($students);
Output:
array(2) {
[2]=>
array(2) {
["id"]=>
string(1) "2"
["name"]=>
string(4) "John"
}
[1]=>
array(2) {
["id"]=>
string(1) "1"
["name"]=>
string(5) "Billy"
}
}
The return value depends on the expression. A location path like //user[student='yes'] or name returns a DOMNodeList. But you can cast the node list directly in Xpath. string(name) will return the contents of the first name child node or an empty string.
How can I make it an array or an object so I can apprach each value by its key?
Just for clarification, you've got an object so far, it's the SimpleXMLElement and you're using then $tt variable to access it:
...
var_dump($tt->student);
var_dump($tt->id);
var_dump($tt->name);
...
Now that $tt variable comes from another variable, namely by iterating over it, and the other variable is named $tmpTemplate:
...
foreach ($tmpTemplate as $tt) {
var_dump($tt->student);
...
That variable by the way is an array. So you can use it by using the index (starting at zero) to access each <user> element containing a <student> child-element with the value "student" in document-order (as you formulated the xpath for it):
$tmpTemplate[0] contains the first user SimpleXMLElement.
$tmpTemplate[1] contains the second user SimpleXMLElement.
... and so on and so forth.
I hope this makes this a bit more visible.
Try with this php function
xml_parse_into_struct
sample from php manual
<?php
$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);
?>
You can use simplexml_load_file, which convert xml to object.
For instance :
$users = simplexml_load_file("users.xml");
foreach($users as $user) {
...
}
$rss_tags = array(
'drawNo',
'drawTime',
'result',
);
$rss_item_tag = 'draw';
$rss_url = "http://applications.opap.gr/DrawsRestServices/kino/drawDate/21-12-2014.xml";
$rssfeed = rss_to_array($rss_item_tag,$rss_tags,$rss_url);
echo '<pre>';
print_r($rssfeed);
/*$total=1;
foreach($rssfeed as $item)
{
if($total<750){
echo '<div><h1>Κλήρωση: '.$item['drawNo']. ' Αριθμοί: ' .$item['result'].'</h1></div>';
$total++;
}
}
*/
function rss_to_array($tag, $array, $url) {
$doc = new DOMdocument();
$doc->load($url);
$rss_array = array();
$items = array();
foreach($doc->getElementsByTagName($tag) AS $node) { //se auth thn epanalhpsh epanalamvenete toses fores oses oi klhrwseis tis hmeras
foreach($array AS $key => $value) { //$array einai ta rss tags
if($value=="result"){
for($i=1;$i<=20;$i++){$items["result"] = $node->getElementsByTagName("result")->item(0)->nodeValue;}
}
$items[$value] = $node->getElementsByTagName($value)->item(0)->nodeValue;
}
array_push($rss_array, $items);
}
return $rss_array;
}
Hello phpers, this is my code to read some xml information but i have a big big big problem.
Firstly check the xml source:
http://applications.opap.gr/DrawsRestServices/kino/drawDate/21-12-2014.xml
The structure is like that:
<draws>
<draw>
<drawNo>
<drawTime>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
<result>
and my code returns only the first entry of the but i want to get both 20 entries could someone help me?
I'm not sure what exactly do you want to output, but maybe this will suit your purpose.
The code below converts xml to array.
<?php
$xmlstring = file_get_contents("http://applications.opap.gr/DrawsRestServices/kino/drawDate/21-12-2014.xml");
// converts $xmlstring to multidimensional array
$arrayMD = json_decode(json_encode((array) simplexml_load_string($xmlstring)), true);
echo "<pre>";
var_dump($arrayMD);
echo "</pre>";
// converts multidimensional array to one-dimensional array
// in other words: "flattens" a multidimensional array
$array = new RecursiveIteratorIterator(new RecursiveArrayIterator($arrayMD));
foreach($array as $v) {
echo $v . "<br>";
}
?>
The output would be as follows:
array(1) {
["draw"]=>
array(157) {
[0]=>
array(3) {
["drawNo"]=>
string(6) "475781"
["drawTime"]=>
string(25) "2014-12-21T09:00:00+02:00"
["result"]=>
array(20) {
[0]=>
string(1) "6"
[1]=>
string(1) "7"
[2]=>
string(2) "12"
[3]=>
string(2) "13"
[4]=>
string(2) "15"
[5]=>
string(2) "16"
...
Reference:
simplexml_load_string
json_encode
json_decode (When second parameter is set to TRUE, returned objects will be converted into associative arrays.)
JSON Predefined Constants
(array) - cast to array, Type Juggling
How to Flatten a Multidimensional Array?
Update:
To access some specific element of the multidimensional array:
$someVar = $arrayMD["draw"][0]["result"][7];
echo $someVar; // outputs: 12
Additionally, have a look at the list function (assigns variables as if they were an array) or extract (imports variables into the current symbol table from an array).
Or the easiest way is just to use several foreach to output them, sum the numbers, select every fifth "result" value of every "draw" or anything else. (This depends on what are you going to do with those values next.)
Sample XML:
<root>
<ratings>3</ratings>
<ratings>5</ratings>
<ratings>7</ratings>
</root>
The following code is the basis for my small application, it works as would be expected:
<?php
// $xml is some simplexml object
sizeof($xml->ratings); //3
foreach($xml->ratings as $rating){
echo($rating->value."::"); //this echoes all 3 rating values: 3::5::7
}
?>
This next code, which I would normally consider to be equivalent is not. And I have no idea why:
<?php
// $xml is some simplexml object
$ratings = $xml->ratings;
sizeof($ratings); //3, all is well so far
foreach($ratings as $rating){
echo($rating."::");
/*this echoes a never-ending list of ratings,
looking like 3::5::5::5::5::5::5::5...... */
}
?>
My feeling is that the assignment operator is casting the array of simplexml objects (ratings objects) as something odd, but have no clue as to how.
Other little hints:
var_dump($xml);
/* Output is:
object(SimpleXMLElement)#7 (1) {
["ratings"]=>
array(3) {
[0]=>
string(1) "3"
[1]=>
string(1) "5"
[2]=>
string(1) "7"
}
}
*/
var_dump($ratings);
/* Output is:
object(SimpleXMLElement)#6 (1) {
[0]=>
string(1) "3"
}
*/
Your echos are not the same:
echo($rating."::");
should be
echo($rating->value."::");
Ok, cleaning up some of my own work. After attempting to simplify my issue more, I was not able to prove it. After messing with the actual code, I assume this means I have some sort of mutating object elsewhere in my app that is going bonkers and creating weird results in this xml parsing. Sorry for the confusion and needless question (I guess this proves why i'm trying to refactor some of my complexity out of this app).
As a parting gift, here is the test-suite of code that I used (from simple to more realistic) that I used to prove that all worked as advertised:
<?php
$string = <<<XML
<?xml version='1.0'?>
<root>
<ratings>3</ratings>
<ratings>5</ratings>
<ratings>7</ratings>
</root>
XML;
$xml = simplexml_load_string($string);
var_dump($xml);
echo("Size:".sizeof($xml->ratings)."\n");
foreach($xml->ratings as $rating){
echo($rating."::");
}
echo("\n"."------"."\n");
$ratings = $xml->ratings;
echo("Size:".sizeof($ratings)."\n");
foreach($ratings as $rating){
echo($rating."::");
}
echo("\n\n\n\n"."||||New Example||||"."\n\n\n\n");
$stringthree = <<<XML
<root attr1="val" attr2="desc">
<field-one>val</field-one>
<elm-two attr-name="foo">elmTwoVal1</elm-two>
<elm-three>elmThreeVal1</elm-three>
<elm-two attr-name="bar">elmTwoVal2</elm-two>
<elm-three>elmThreeVa2</elm-three>
<elm-two attr-name="bear">elmTwoVal3</elm-two>
<elm-three>elmThreeVal3</elm-three>
</root>
XML;
$xmlthree = simplexml_load_string($stringthree);
var_dump($xmlthree);
echo("Size:".sizeof($xmlthree->{'elm-two'})."\n");
foreach($xmlthree->{'elm-two'} as $elm){
echo($elm."::");
}
echo("\n"."------"."\n");
$elmMain = $xmlthree->{'elm-two'};
echo("Size:".sizeof($elmMain)."\n");
foreach($elmMain as $elm){
echo($elm."::");
}
?>