get xml element using php - php

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.

Related

Unable to get node from simplexml_load_string

I understand this question has been asked, but all solutions I've found have not worked for me.
Given this:
SimpleXMLElement Object
(
[0] =>
<test>
<blah>
<x>
filler
</x>
</blah>
</test>
)
How do I get the <x> value?
I've tried
$doc = simplexml_load_string($xml_response);
print_r($doc->test->blah->x);
print_r($doc[0]->test->blah->x);
print_r($doc->{'0'}->test->blah->x);
print_r((string)$doc->{'0'}->test->blah->x);
print_r((string)$doc[0]->test->blah->x);
print_r((string)$doc->test->blah->x);
Here's the raw xml:
1.0" encoding="UTF-8" ?>
<xxx>
<test>
<blah>
<x>fillertexthere</x>
</blah>
<fillertexthere</Reason>
</test>
</xxx>%
Your SimpleXMLElement contains one string. I think that is because your xml contains < and >.
What you could do is first use htmlspecialchars_decode and then load your string.
(I have removed this line <fillertexthere</Reason> and % from your raw xml)
$xml_response = <<<DATA
<?xml version="1.0" encoding="UTF-8" ?>
<xxx>
<test>
<blah>
<x>fillertexthere</x>
</blah>
</test>
</xxx>
DATA;
$xml_response = htmlspecialchars_decode($xml_response);
var_dump($xml_response);
This will look like:
object(SimpleXMLElement)#1 (1) {
["test"]=>
object(SimpleXMLElement)#2 (1) {
["blah"]=>
object(SimpleXMLElement)#3 (1) {
["x"]=>
string(14) "fillertexthere"
}
}
}
You can echo the value of x like this:
echo $doc->test->blah->x;

PHP iterating over an XML

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) {
...
}

xml export php code returns only one parent of the xml file i need them all

$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.)

translating sql-like syntax to xpath in PHP

I am writing a class to read content of an xml with mysql-like syntax (of course it not completly the same syntax and I ignore many things, just want to have some basics).
First of all, statements look like:
"SELECT name passwd FROM table WHERE id = 1 and description = 'desc'"
Some basic rules:
There has to be a whitespace between everything
not more than two comparisons after the "WHERE"
I haven't done anything but the method for the select statement.
I explode the statement, sort it into an array and then try to translate it to DOMXpath
It works if there's no WHERE. But I'm struggling with the where-clauses (here what I have done so far:)
statement: "SELECT name pw FROM user WHERE id = '1' and description = 'test or test2'"
the array looks like:
array(4) {
["type"]=>
string(6) "SELECT"
["searchFields"]=>
array(2) {
["searchField0"]=>
string(4) "name"
["searchField1"]=>
string(2) "pw"
}
["tableName"]=>
string(4) "user"
["comparer"]=>
array(2) {
["where0"]=>
array(3) {
["field"]=>
string(2) "id"
["operator"]=>
string(1) "="
["value"]=>
string(3) "'1'"
}
["where1"]=>
array(4) {
["splitTag"]=>
string(3) "and"
["field"]=>
string(11) "description"
["operator"]=>
string(1) "="
["value"]=>
string(15) "'test or test2'"
}
}
}
How I'm trying to convert the statement to Xpath with the following code:
for ($i = 0; $i < count($arrQuery['searchFields']); $i++) {
$conditions = "";
foreach ($arrQuery['comparer'] as $value) {
switch (count($arrQuery['comparer'])) {
case 1:
$conditions .= '//parent::content[#name="'.$value['field'].'" and text()='.$value['value'].']';
break;
case 2:
if (!isset($value['splitTag']) || $value['splitTag'] == "and") {
$conditions .= '//parent::content[#name="'.$value['field'].'" and text()='.$value['value'].']';
break;
} else {
//$conditions .= 'content[#'.$value['field'].' and text()='.$value['value'].']//parent::*';
}
break;
}
}
$xpathquery = '//datarange[#name="'.$arrQuery['tableName'].'"]'.$conditions.'//content[#name="'.$arrQuery['searchFields']['searchField'.$i].'"]';
$nodeList = $this->xpath->query($xpathquery);
foreach ($nodeList as $node) {
$arrContent['searchField'.$i][] = $node->nodeValue;
}
}
My first Point is: if the condition of the if-clause in case 2 is confirmed, the created xpath isn't working (might be problem with parent or my logic)
My second Point is: I still have no idea how to handle the case that the condition doesn't match and $value['splitTag'] is "or". If anyone has a hint how to solve that, I would be very thankfull.
/EDIT: Ok, thanks for the tip, here's an example of my xml:
<database>
<datarange id="user">
<dataset id="0">
<content name="id">
1
</content>
<content name="description">
test or test2
</content>
<content name="name">
Name
</content>
<content name="pw">
Passwort
</content>
</dataset>
<dataset id="1">
<content name="name">
Name2
</content>
<content name="pw">
Passwort2
</content>
</dataset>
</datarange>
<datarange id="config">
<dataset id="0">
<content name="type">
command
</content>
<content name="name">
lab
</content>
<content name="type">
request
</content>
<content name="target">
target_name
</content>
<content name="desc">
Address Book
</content>
</dataset>
</datarange>
</database>
Given your input document and the query: SELECT name pw FROM user WHERE id = '1' and description = 'test or test2 you will have to build yourself the following XPath to get to the dataset node that has the values you need:
//datarange[#id = 'user']/dataset
[normalize-space(content[#name = 'id']) = '1']
[normalize-space(content[#name = 'description']) = 'test or test2']
This one will give you the dataset node that you can then run the following on:
normalize-space(content[#name = 'name'])
to get the name and:
normalize-space(content[#name = 'pw'])
Here's a simple XSLT to test it:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="//datarange[#id = 'user']/dataset
[normalize-space(content[#name = 'id']) = '1']
[normalize-space(content[#name = 'description']) = 'test or test2']"/>
</xsl:template>
<xsl:template match="dataset">
name: <xsl:value-of select="normalize-space(content[#name = 'name'])"/>
pwd: <xsl:value-of select="normalize-space(content[#name = 'pw'])"/>
</xsl:template>
</xsl:stylesheet>
When applied to your input document it will produce:
name: Name
pwd: Passwort
You can now factor it into your query SQL-like-to-XPath engine.
One more thing though. If you can upgrade to XPath 2.0 you may want to try the conditional and quantified expressions to make your XPath more query-like. And who knows, maybe you won't need a SQL-like syntax to begin with. Plus there's XQuery.

Need to extract values from a XML file

I have a XML file, and the layout is such
<author>
<name></name>
<iso></iso>
<price></price>
</author>
I know how it loops. I want to know how I can extract the value of
<name>
Thanks
Jean
[edit]
my apologies, if in the
<author>
<name>
<first_name></first_name>
<last_name></lastname>
</name>
</author>
I want to extract first_name
Use simplexml or similar:
<?php
$string = <<<XML
<author>
<name>
<first_name>John</first_name>
<last_name>Smith</last_name>
</name>
</author>
XML;
$xml = simplexml_load_string($string);
var_dump($xml);
?>
Will output something like this:
object(SimpleXMLElement)#1 (1) {
["name"]=>
object(SimpleXMLElement)#2 (2) {
["first_name"]=>
string(4) "John"
["last_name"]=>
string(5) "Smith"
}
}
And you can access the name like this:
echo $xml->name->first_name; // outputs 'John'
echo $xml->name->last_name; // outputs 'Smith'
Use SimpleXML.
Edit: I see. That wasn't showing up before. Try this:
$xml = simple_xml_load_string([your XML string])
echo $xml->name;
Does that work?

Categories