I'm learning how to parse XML with PHP's simple XML. My code is:
<?php
$xmlSource = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?> <Document xmlns=\"http://www.apple.com/itms/\" artistId=\"329313804\" browsePath=\"/36/6407\" genreId=\"6507\"> <iTunes> myApp </iTunes> </Document>";
$xml = new SimpleXMLElement($xmlSource);
$results = $xml->xpath("/Document/iTunes");
foreach ($results as $result){
echo $result.PHP_EOL;
}
print_r($result);
?>
When this runs it returns a blank screen, with no errors. If I remove all the attributes from the Document tag, it returns :
myApp SimpleXMLElement Object ( [0] => myApp )
Which is the expected result.
What am I doing wrong? Note that I don't have control over the XML source, since it's coming from Apple.
Your xml contains a default namespace. In order to get your xpath query to work you need to register this namespace, and use the namespace prefix on every xpath element you are querying (as long as these elements all fall under the same namespace, which they do in your example):
$xml = new SimpleXMLElement( $xmlSource );
// register the namespace with some prefix, in this case 'a'
$xml->registerXPathNamespace( 'a', 'http://www.apple.com/itms/' );
// then use this prefix 'a:' for every node you are querying
$results = $xml->xpath( '/a:Document/a:iTunes' );
foreach( $results as $result )
{
echo $result . PHP_EOL;
}
For the part about the default namespace, read fireeyedboy's answer. As mentionned, you need to register a namespace if you want to use XPath on nodes that are in the default namespace.
However, if you don't use xpath(), SimpleXML has its own magic that selects the default namespace automagically.
$xmlSource = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?> <Document xmlns=\"http://www.apple.com/itms/\" artistId=\"329313804\" browsePath=\"/36/6407\" genreId=\"6507\"> <iTunes> myApp </iTunes> </Document>";
$Document = new SimpleXMLElement($xmlSource);
foreach ($Document->iTunes as $iTunes)
{
echo $iTunes, PHP_EOL;
}
this is general example
foreach ($library->children() as $child)
{
echo $child->getName() . ":\n";
foreach ($child->attributes() as $attr)
{
echo $attr->getName() . ': ' . $attr . "\n";
}
foreach ($child->children() as $subchild)
{
echo $subchild->getName() . ': ' . $subchild . "\n";
}
echo "\n";
}
for more information check this :
http://www.yasha.co/XML/how-to-parse-xml-with-php-simplexml-DOM-Xpath/article-1.html
This line:
print_r($result);
is outside the foreach loop. Maybe you should try
print_r($results);
instead.
Seems if you use the wildcard (//) on xpath it will work. Also, not sure why but if you remove the namespace attribute (xmlns) from the Document element, your current code will work. Maybe because a prefix isn't defined? Anyway, following should work:
$results = $xml->xpath("//iTunes");
foreach ($results as $result){
echo $result.PHP_EOL;
}
Related
Here is the XML I am parsing:
https://seekingalpha.com/api/sa/combined/AAPL.xml
When I grab and parse the XML with simplexml_load_file($url) and then do a var_dump on that, it shows that the only children of every "item" are "title", "link", "guid", and "pubDate."
I am trying to access the node "sa:author_name." Why isn't it a child of "item"? Maybe I am misunderstanding something about how XML files are structured. Help me my children are missing lol
To get the data in sa:author_name you have to use the namespace https://seekingalpha.com/api/1.0.
You can for example use a foreach and loop the children using the namespace.
$url = "https://seekingalpha.com/api/sa/combined/AAPL.xml";
$xml = simplexml_load_file($url);
foreach ($xml->channel->item as $item) {
foreach ($item->children("https://seekingalpha.com/api/1.0") as $child) {
if ($child->getName() === "author_name") {
echo $child . "<br>";
}
}
}
Another way you could do it is using an xpath expression:
$authorNames = $xml->xpath('/rss/channel/item/sa:author_name');
foreach ($authorNames as $authorName) {
echo $authorName . "<br>";
}
Which will result in:
Yoel Minkoff
DoctoRx
SA Transcripts
Bill Maurer
etc..
I have following xml getting loaded in my PHP code;
<SiteAlarmDetails>
<AlertId>89637</AlertId>
<SiteCode>20157498</SiteCode>
<SiteName>newport</SiteName>
</SiteAlarmDetails>
$alertXml = simplexml_load_string( $tableAlarm->AlarmDetails);
echo (string) $alertXml->AlertId; //prints **89637**
Now I try to traverse this XML nodes;
foreach($alertXml->children() as $alerts)
{
$alertId = (string)$alerts->AlertId;
echo $alertId;//I do not see anything
}
Is above right approach to traverse AlertId in the foreach loop?
Trying simple foreach will be helpful. Just for accessing single value (eg AlertId) you can use $alertXml->AlertId;.
Try this code snippet here
<?php
ini_set('display_errors', 1);
$xmlString=<<<XML
<SiteAlarmDetails>
<AlertId>89637</AlertId>
<SiteCode>20157498</SiteCode>
<SiteName>newport</SiteName>
</SiteAlarmDetails>
XML;
$alertXml = simplexml_load_string( $xmlString);
foreach($alertXml as $key => $child)
{
echo $key ."=".(string)$alertXml->{$key};
echo PHP_EOL;
}
Output:
AlertId=89637
SiteCode=20157498
SiteName=newport
Below code is for export data from mysql table as xml file. I have tried several code but not getting the result. Please check and help me.
Currently getting result is
8sarathsarathernakulam423432washington9rahulrahulernakulam21212121newyork10aaaa3london11bbbb1newyork12cccc2washington13dddd3london
Code
<?php
require_once "classes/dbconnection-class.php";
if(isset($_POST['export'])){
header('Content-type: text/xml');
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
$root_element = "addressbook"; //fruits
$xml .= "<$root_element>";
$query = "SELECT AB.id, AB.name, AB.firstname, AB.street, AB.zipcode, AB.city_id, CI.city FROM address_book AS AB INNER JOIN city AS CI ON AB.city_id = CI.id";
$result = $mysqli->query($query);
if (!$result) {
die('Invalid query: ' . $mysqli->error());
}
while($result_array = $result->fetch_assoc()){
$xml .= "<address>";
foreach($result_array as $key => $value)
{
//$key holds the table column name
$xml .= "<$key>";
//embed the SQL data in a CDATA element to avoid XML entity issues
$xml .= "<![CDATA[$value]]>";
//and close the element
$xml .= "</$key>";
}
$xml.="</address>";
}
$xml .= "</$root_element>";
header ("Content-Type:text/xml");
//header('Content-Disposition: attachment; filename="downloaded.xml"');
echo $xml;
}
?>
Browser shows
<?xml version="1.0" encoding="UTF-8"?><addressbook><address><id><![CDATA[8]]></id><name><![CDATA[sarath]]></name><firstname><![CDATA[sarath]]></firstname><street><![CDATA[ernakulam]]></street><zipcode><![CDATA[42343]]></zipcode><city_id><![CDATA[2]]></city_id><city><![CDATA[washington]]></city></address><address><id><![CDATA[9]]></id><name><![CDATA[rahul]]></name><firstname><![CDATA[rahul]]></firstname><street><![CDATA[ernakulam]]></street><zipcode><![CDATA[2121212]]></zipcode><city_id><![CDATA[1]]></city_id><city><![CDATA[newyork]]></city></address><address><id><![CDATA[10]]></id><name><![CDATA[a]]></name><firstname><![CDATA[a]]></firstname><street><![CDATA[a]]></street><zipcode><![CDATA[a]]></zipcode><city_id><![CDATA[3]]></city_id><city><![CDATA[london]]></city></address><address><id><![CDATA[11]]></id><name><![CDATA[b]]></name><firstname><![CDATA[b]]></firstname><street><![CDATA[b]]></street><zipcode><![CDATA[b]]></zipcode><city_id><![CDATA[1]]></city_id><city><![CDATA[newyork]]></city></address><address><id><![CDATA[12]]></id><name><![CDATA[c]]></name><firstname><![CDATA[c]]></firstname><street><![CDATA[c]]></street><zipcode><![CDATA[c]]></zipcode><city_id><![CDATA[2]]></city_id><city><![CDATA[washington]]></city></address><address><id><![CDATA[13]]></id><name><![CDATA[d]]></name><firstname><![CDATA[d]]></firstname><street><![CDATA[d]]></street><zipcode><![CDATA[d]]></zipcode><city_id><![CDATA[3]]></city_id><city><![CDATA[london]]></city></address></addressbook>
When we are dealing with XML and HTML, the best way to act is ever through a parser.
In this particular situation, operating with a parser guarantees a valid XML and a clean, short code.
After defining mySQL query, we init a new DOMDocument with version and encoding, then we set his ->formatOutput to True to print out XML in indented format:
$query = "SELECT AB.id, AB.name, AB.firstname, AB.street, AB.zipcode, AB.city_id, CI.city FROM address_book AS AB INNER JOIN city AS CI ON AB.city_id = CI.id";
$dom = new DOMDocument( '1.0', 'utf-8' );
$dom ->formatOutput = True;
Then, we create the root node and we append it to DOMDocument:
$root = $dom->createElement( 'addressbook' );
$dom ->appendChild( $root );
At this point, after executing mySQL query, we perform a while loop through each resulting row; for each row, we create an empty node <address>, then we perform a foreach loop through each row's field. For each field, we create an empty childnode with tag as field key, then we append to childnode the field value as CDATA and the same childnode to <address> node; at the end of each while loop, each <address> node is appended to root node:
$result = $mysqli->query( $query );
while( $row = $result->fetch_assoc() )
{
$node = $dom->createElement( 'address' );
foreach( $row as $key => $val )
{
$child = $dom->createElement( $key );
$child ->appendChild( $dom->createCDATASection( $val) );
$node ->appendChild( $child );
}
$root->appendChild( $node );
}
Now, your XML is ready.
If you want save it to a file, you can do it by:
$dom->save( '/Your/File/Path.xml' );
Otherwise, if you prefer send it as XML you have to use this code:
header( 'Content-type: text/xml' );
echo $dom->saveXML();
exit;
If you want instead output it in HTML page, you can write this code:
echo '<pre>';
echo htmlentities( $dom->saveXML() );
echo '</pre>';
See more about DOMDocument
Go to your phpmyadmin database export and select xml in file format.
Replace
$xml .= "<![CDATA[$value]]>";
with
$xml .= $value;
IF you want to have it format it "nicely" in the browser add an:
echo "<pre>";
before the:
echo $xml;
Please note this WILL BREAK the XML file, but it will look good in the browser.... if that is what you are after...
I would suggest to use libraries like SimpleXMLElement etc. to create XML documents.
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><{$root_element}></{$root_element}>");
while($result_array = $result->fetch_assoc()){
foreach($result_array as $key => $value)
{
$address = $xml->addChild("address");
//embed the SQL data in a CDATA element to avoid XML entity issues
$addressFields = $address->addChild('"' . $key . '"', "<![CDATA[$value]]>");
//No need to close the element
}
}
Header('Content-type: text/xml');
print($xml->asXML());
I wrote a php code for retrieving some data from a XML file into a variable.
This is the XML file:
<Server>
<Server1>
<ipaddress>10.3.2.0</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.1</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.2</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.3</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
</Server>
This is the PHP code:
$x = $xmlDoc->getElementsByTagName("ipaddress");
Here i want to display the content of $x by index value, something like
echo $x[0]->nodeValue;
How could I do that?
I assume you used DOMDocument for the XML parsing. When invoking getElementsByTagName you will receive a DOMNodeList not an array.
DOMNodeList implements Traversable so it can be used in foreach loops.
foreach ($x as $item) {
var_dump($item->nodeValue);
}
If you just want a specific item use the item method.
$x->item(0)->nodeValue;
You can access ipaddress like below.
$xml = simplexml_load_file("yourxml.xml");
$result = $xml->xpath('//Server1');
foreach($result as $item){
echo "IP Address:".$item->ipaddress
echo "<br/>";
}
The demo.
$xml = simplexml_load_file($path_to_your_xml_file);
foreach($xml->Server1 as $server) {
echo $server->ipaddress . '<br>';
}
Or you could just do:
echo $xml->Server1[0]->ipaddress;
I'm trying to get the entry->id and entry->cap:parameter->value for every entry in the RSS feed.... below is the code I'm using. It is displaying the id correctly however it is not displaying the value field.... please help.
$url = 'http://alerts.weather.gov/cap/us.php?x=1';
$cap = simplexml_load_file($url);
foreach($cap->entry as $entry){
echo 'ID: ', $entry->id, "\n";
echo 'VTEC: ', $entry->children('cap', true)->parameter->value, "\n";
echo "<hr>";
}
Thanks for the help in advance.
The <value> element is not in the same namespace as <cap:parameter>:
<cap:parameter>
<valueName>VTEC</valueName>
<value>/O.CON.KMPX.FL.W.0012.000000T0000Z-110517T1800Z/</value>
</cap:parameter>
So you have to call children() again.
Code (demo)
$feed = simplexml_load_file('http://alerts.weather.gov/cap/us.php?x=1');
foreach ($feed->entry as $entry){
printf(
"ID: %s\nVTEC: %s\n<hr>",
$entry->id,
$entry->children('cap', true)->parameter->children()->value
);
}