Get the attributes and values from xml file - php

I have following xml file:
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>03/23/2015</transaction_date>
<date>05/18/2015</date>
<username>musiclvr24</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8785090</link>
<comment><![CDATA[Ordering was very easy! The whole website was very informative and very useful as a health resource. Thank you very much!]]></comment>
</ROW>
Here is my php file to parse xml file.
<pre>
<?php
$seller_id = 113;
$xml = simplexml_load_string(file_get_contents("http://widget.atings.com/widget/snippet/?seller_id=$seller_id"));
foreach($xml->ROW as $row){
//echo $row,'="',$s,"\"\n"; // to get all rows
var_dump($row);
echo '<div class="spans"></div>';
}
//var_dump($xml->ROW) // to get single row
?>
</pre>
I need to get each row's attributes and values displayed on newly created divs for each row. How can I achieve this?

If possible add some main tags at start and end of your XML and rest of your code will work fine...
<document>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>03/23/2015</transaction_date>
<date>05/18/2015</date>
<username>musiclvr24</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8785090</link>
<comment><![CDATA[Ordering was very easy! The whole website was very informative and very useful as a health resource. Thank you very much!]]></comment>
</ROW>
</document>

You need to enclosed some main tags like "ROWS" which enclosed other tags. please check below XML and code to access element value.
$xml = <<<XML
<ROWS>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
</ROWS>
XML;
$xml = simplexml_load_string($xml);
foreach($xml as $row){
echo $row->rating;
echo $row->answers;
}

$xml=simplexml_load_file("http://widget.atings.com/widget/snippet/?seller_id=$seller_id") or die("Error: Cannot create object");
foreach($xml->children() as $child) :
endforeach;
// Load xml file content
$xml=simplexml_load_file("http://example.com/xml.xml") or die("Error: Cannot create object");
//Get children with foreach.
foreach($xml->children() as $child)
{ $inc = 1;
foreach($child->children() as $childs){
foreach($childs->children() as $childss){
if($inc == 7) :
if($childss->getName() === 'description') :
echo '<div class="descriptionOfNisab">'. $childss . '</div>';
endif;
endif;
}
$inc ++;
}
}

Related

XML Assign More Than One Result To PHP Variable

I have done a bit of searching on this, but am just not sure I am searching for the right thing. Examples and things I have found have just confused me and possibly sent me in the wrong direction.
I am trying to figure out a php while statement, or if statement to return the results of XML output. The thing is the row/section I need may not always be the same number of results returned. For example there are ShoutCast streams, some have 1 mount point, and some have 3 mount points. Each mount point can have a different amount of listeners tuned in to that particular mount.
My Goal: To get the integer from all mount points returned in the XML, add them together to make a grand total of listeners.
The XML
<centovacast version="3.1.2" host="host.net">
<response type="success">
<message>Complete</message>
<data>
<status>
<mount>/stream</mount>
<sid>1</sid>
<listenercount>31</listenercount>
<genre>Blues</genre>
<url>http://www.websiteurl.com</url>
<title>Streams Name</title>
<currentsong>Artist Name - Track Name</currentsong>
<bitrate>128</bitrate>
<sourceconnected>1</sourceconnected>
<codec>audio/mpeg</codec>
<displayname>/stream</displayname>
<serverstate>1</serverstate>
<appstate>
<sctrans2>1</sctrans2>
</appstate>
<sourcestate>1</sourcestate>
<reseller/>
<useserver>1</useserver>
<ipaddress>11.11.111.111</ipaddress>
<port>8031</port>
<proxy>0</proxy>
<servertype>ShoutCast2</servertype>
<sourcetype>sctrans2</sourcetype>
</status>
<mountpoints>
<row>
<mount>/stream</mount>
<sid>1</sid>
<listenercount>31</listenercount>
<genre>Blues</genre>
<url>http://www.websiteurl.com</url>
<title>Stream Title Name</title>
<currentsong>Artist Name - Track Name</currentsong>
<bitrate>128</bitrate>
<sourceconnected>1</sourceconnected>
<codec>audio/mpeg</codec>
<displayname>/stream</displayname>
</row>
<row>
<mount>/live</mount>
<sid>2</sid>
<listenercount>0</listenercount>
<genre/>
<url/>
<title/>
<currentsong/>
<bitrate>0</bitrate>
<sourceconnected>0</sourceconnected>
<codec/>
<displayname>/live</displayname>
</row>
</mountpoints>
</data>
</response>
</centovacast>
So on the above I know how to pull the listeners for each mount individually using the following code.
$countlisteners->response->data->mountpoints->row[0]->listenercount;
That gives me the result for the first mount, and switching the 0 to a 1 gives me the second mount, so on and so forth.
What I need is for php that will count how many of those mounts exist, and assign each result to a variable I can then use to add together to get a grand total. Is there a way to do this?
What about doing something like this?
$countlisteners = simplexml_load_file('http://urltoxml.com');
foreach($countlisteners->response->data->mountpoints->row->listenercount as $result){
$total = $result;
echo $total;
}
You can use DOMDocument for extracting all mountpoint tags
<?php
$xml="Your xml document content here";
$dom = new DOMDocument;
$dom->loadXML($xml);
$books = $dom->getElementsByTagName('mountpoints');
foreach ($mountpoints as $mountpoints) {
echo $mountpoints->nodeValue;
//you can add your count variable here
//nodeValues can be assigned to varables
}
?>
I figured it out. So simplistic, yet hard to figure out.
$total = 0;
foreach($countlisteners->response->data->mountpoints->row as $result){
$total += $result->listenercount;
$items++;
}
echo $total;
You normally do that with Xpath. It's a query language for XML documents.
You're interested in all listenercount elements, the Xpath expression for these elements could be as simple as:
//listenercount
When you now use SimpleXML to parse the document, the following line of code gives you three SimpleXMLElements inside an array that represent the three values you want to create the sum of:
$array = simplexml_load_string($buffer)->xpath('//listenercount');
As you need the sum of the integer values of these three elements, it can be easily processed with array_map and array_sum:
$sum = array_sum(array_map('intval', $array));
And this gives you in $sum what you're looking for:
var_dump($sum); # int(62)
I hope this sheds you some light why it's often better to get the information you're looking for with an xpath query from the document instead of writing many lines of code to traverse the document "on your own".
The full example:
$buffer = <<<XML
<centovacast version="3.1.2" host="host.net">
<response type="success">
<message>Complete</message>
<data>
<status>
<mount>/stream</mount>
<sid>1</sid>
<listenercount>31</listenercount>
<genre>Blues</genre>
<url>http://www.websiteurl.com</url>
<title>Streams Name</title>
<currentsong>Artist Name - Track Name</currentsong>
<bitrate>128</bitrate>
<sourceconnected>1</sourceconnected>
<codec>audio/mpeg</codec>
<displayname>/stream</displayname>
<serverstate>1</serverstate>
<appstate>
<sctrans2>1</sctrans2>
</appstate>
<sourcestate>1</sourcestate>
<reseller/>
<useserver>1</useserver>
<ipaddress>11.11.111.111</ipaddress>
<port>8031</port>
<proxy>0</proxy>
<servertype>ShoutCast2</servertype>
<sourcetype>sctrans2</sourcetype>
</status>
<mountpoints>
<row>
<mount>/stream</mount>
<sid>1</sid>
<listenercount>31</listenercount>
<genre>Blues</genre>
<url>http://www.websiteurl.com</url>
<title>Stream Title Name</title>
<currentsong>Artist Name - Track Name</currentsong>
<bitrate>128</bitrate>
<sourceconnected>1</sourceconnected>
<codec>audio/mpeg</codec>
<displayname>/stream</displayname>
</row>
<row>
<mount>/live</mount>
<sid>2</sid>
<listenercount>0</listenercount>
<genre/>
<url/>
<title/>
<currentsong/>
<bitrate>0</bitrate>
<sourceconnected>0</sourceconnected>
<codec/>
<displayname>/live</displayname>
</row>
</mountpoints>
</data>
</response>
</centovacast>
XML;
$array = simplexml_load_string($buffer)->xpath('//listenercount');
$sum = array_sum(array_map('intval', $array));
var_dump($sum);

Get Child Data from large XML file

I have an large XML file (26,434 lines) that I'm working with.
Excerpt XML:
<row name="Scorned Syndicate" shortName="-SS-" allianceID="1778325832" executorCorpID="98020631" memberCount="29" startDate="2010-08-14 00:29:00">
<rowset name="memberCorporations" key="corporationID" columns="corporationID,startDate">
<row corporationID="98020119" startDate="2011-02-09 04:52:00" />
<row corporationID="98020631" startDate="2011-02-23 23:55:00" />
</rowset>
</row>
By searching here I've found how I can get the alliance name and short name but now I want the corporationID
$xml = new XMLReader();
$xml->XML( $xmlString );
while( $xml->read() ) {
if( 'row' === $xml->name ) {
echo $xml->getAttribute('name') . ' '. $xml->getAttribute('shortName').'<br>';
$xml->next();
}
}
I researched enough to know I need to utilize a streaming reader for efficiency but not sure how to get the last part of my data.
When you use the next() function in the XMLReader the subtrees are skipped. Your while statement should advance it through automatically. If you need to see output before the entire file is parsed you might consider ob_flush, otherwise it would be better to create an array so that the format is more customizable.

PHP script to echo VLC now playing XML attributes

I've been searching for a while on this and haven't had much luck. I've found plenty of resources showing how to echo data from dynamic XML, but I'm a PHP novice, and nothing I've written seems to grab and print exactly what I want, though from everything I've heard, it should be relatively easy. The source XML (located at 192.168.0.15:8080/requests/status.xml) is as follows:
<root>
<fullscreen>0</fullscreen>
<volume>97</volume>
<repeat>false</repeat>
<version>2.0.5 Twoflower</version>
<random>true</random>
<audiodelay>0</audiodelay>
<apiversion>3</apiversion>
<videoeffects>
<hue>0</hue>
<saturation>1</saturation>
<contrast>1</contrast>
<brightness>1</brightness>
<gamma>1</gamma>
</videoeffects>
<state>playing</state>
<loop>true</loop>
<time>37</time>
<position>0.22050105035305</position>
<rate>1</rate>
<length>168</length>
<subtitledelay>0</subtitledelay>
<equalizer/>
<information>
<category name="meta">
<info name="description">
000003EC 00000253 00000D98 000007C0 00009C57 00004E37 000068EB 00003DC5 00015F90 00011187
</info>
<info name="date">2003</info>
<info name="artwork_url"> file://brentonshp04/music%24/Music/Hackett%2C%20Steve/Guitar%20Noir%20%26%20There%20Are%20Many%20Sides%20to%20the%20Night%20Disc%202/Folder.jpg
</info>
<info name="artist">Steve Hackett</info>
<info name="publisher">Recall</info>
<info name="album">Guitar Noir & There Are Many Sides to the Night Disc 2
</info>
<info name="track_number">5</info>
<info name="title">Beja Flor [Live]</info>
<info name="genre">Rock</info>
<info name="filename">Beja Flor [Live]</info>
</category>
<category name="Stream 0">
<info name="Bitrate">128 kb/s</info>
<info name="Type">Audio</info>
<info name="Channels">Stereo</info>
<info name="Sample rate">44100 Hz</info>
<info name="Codec">MPEG Audio layer 1/2/3 (mpga)</info>
</category>
</information>
<stats>
<lostabuffers>0</lostabuffers>
<readpackets>568</readpackets>
<lostpictures>0</lostpictures>
<demuxreadbytes>580544</demuxreadbytes>
<demuxbitrate>0.015997290611267</demuxbitrate>
<playedabuffers>0</playedabuffers>
<demuxcorrupted>0</demuxcorrupted>
<sendbitrate>0</sendbitrate>
<sentbytes>0</sentbytes>
<displayedpictures>0</displayedpictures>
<demuxreadpackets>0</demuxreadpackets>
<sentpackets>0</sentpackets>
<inputbitrate>0.016695899888873</inputbitrate>
<demuxdiscontinuity>0</demuxdiscontinuity>
<averagedemuxbitrate>0</averagedemuxbitrate>
<decodedvideo>0</decodedvideo>
<averageinputbitrate>0</averageinputbitrate>
<readbytes>581844</readbytes>
<decodedaudio>0</decodedaudio>
</stats>
</root>
What I'm trying to write is a simple PHP script that echoes the artist's name (In this example Steve Hackett). Actually I'd like it to echo the artist, song and album, but I'm confident that if I'm shown how to retrieve one, I can figure out the rest on my own.
What little of my script which actually seems to work goes as follows. I've tried more than what's below, but I left out the bits that I know for a fact aren't working.
<?PHP
$file = file_get_contents('http://192.168.0.15:8080/requests/status.xml');
$sxe = new SimpleXMLElement($file);
foreach($sxe->...
echo "Artist: "...
?>
I think I need to use foreach and echo, but I can't figure out how to do it in a way that will print what's between those info brackets.
I'm sorry if I've left anything out. I'm not only new to PHP, but I'm new to StackOverflow too. I've referenced this site in other projects, and it's always been incredibly helpful, so thanks in advance for your patience and help!
////////Finished Working Script - Thanks to Stefano and all who helped!
<?PHP
$file = file_get_contents('http://192.168.0.15:8080/requests/status.xml');
$sxe = new SimpleXMLElement($file);
$artist_xpath = $sxe->xpath('//info[#name="artist"]');
$album_xpath = $sxe->xpath('//info[#name="album"]');
$title_xpath = $sxe->xpath('//info[#name="title"]');
$artist = (string) $artist_xpath[0];
$album = (string) $album_xpath[0];
$title = (string) $title_xpath[0];
echo "<B>Artist: </B>".$artist."</br>";
echo "<B>Title: </B>".$title."</br>";
echo "<B>Album: </B>".$album."</br>";
?>
Instead of using a for loop, you can obtain the same result with XPath:
// Extraction splitted across two lines for clarity
$artist_xpath = $sxe->xpath('//info[#name="artist"]');
$artist = (string) $artist_xpath[0];
echo $artist;
You will have to adjust the xpath expression (i.e. change #name=... appropriately), but you get the idea. Also notice that [0] is necessary because xpath will return an array of matches (and you only need the first) and the cast (string) is used to extract text contained in the node.
Besides, your XML is invalid and will be rejected by the parser because of the literal & appearing in the <info name="album"> tag.
If you look at your code again, you are missing a function that turns the first result of the xpath expression into a string of a SimpleXMLElement (casting).
One way to write this once is to extend from SimpleXMLElement:
class BetterXMLElement extends SimpleXMLElement
{
public function xpathString($expression) {
list($result) = $this->xpath($expression);
return (string) $result;
}
}
You then create the more specific SimpleXMLElement like you did use the less specific before:
$file = file_get_contents('http://192.168.0.15:8080/requests/status.xml');
$sxe = new BetterXMLElement($file);
And then you benefit in your following code:
$artist = $sxe->xpathString('//info[#name="artist"]');
$album = $sxe->xpathString('//info[#name="album"]');
$title = $sxe->xpathString('//info[#name="title"]');
echo "<B>Artist: </B>".$artist."</br>";
echo "<B>Title: </B>".$title."</br>";
echo "<B>Album: </B>".$album."</br>";
This spares you some repeated code. This means as well less places you can make an error in :)
Sure you can further on optimize this by allowing to pass an array of multiple xpath queries and returning all values named then. But that is something you need to write your own according to your specific needs. So use what you learn in programming to make programming more easy :)
If you want some more suggestions, here is another, very detailed example using DOMDocument, the sister-library of SimpleXML. It is quite advanced but might give you some good inspiration, I think something similar is possible with SimpleXML as well and this is probably what you're looking for in the end:
Extracting data from HTML using PHP and xPath

Exporting defined elements from XML

I would like to export (or to keep) the subtags which are with the defined attribute in XML. As I don't know the name of this process, I can't find any relevant information about it on the net. And since it's hard to explain, I decided to put an examples for my issue.
Let's say, I have this XML file:
<results>
<result idSite="1">
<row>
<label>category</label>
<visits>2</visits>
<idsubdatatable>5</idsubdatatable>
<subtable>
<row>
<label>uncategorized</label>
<visits>2</visits>
<idsubdatatable>6</idsubdatatable>
<subtable>
<row>
<label>/index</label>
<visits>2</visits>
<url>http://mysite1.com/category/uncategorized/</url>
</row>
</subtable>
</row>
</subtable>
</row>
<row>
<label>about</label>
<visits>1</visits>
<idsubdatatable>7</idsubdatatable>
<subtable>
<row>
<label>/index</label>
<visits>1</visits>
<url>http://mysite1.com/about/</url>
</row>
</subtable>
</row>
</result>
<result idSite="2">
<row>
<label>/calendar</label>
<visitors>1</visitors>
<url>http://mysite2.com/calendar</url>
</row>
</result>
</results>
And I have to parse the results and keep only the rows which are with a <url> attribute. Like this:
After parsing I have to combine these rows in a new XML file, and the final result must be like this:
<result>
<row>
<label>/index</label>
<visits>2</visits>
<url>http://mysite1.com/category/uncategorized/</url>
</row>
<row>
<label>/index</label>
<visits>1</visits>
<url>http://mysite1.com/about/</url>
</row>
<row>
<label>/calendar</label>
<visitors>1</visitors>
<url>http://mysite2.com/calendar</url>
</row>
</result>
Generally I want to do this process in PHP but it maybe in other languages too.
So, if you have any idea to solve this problem, please comment.
I would use an xpath query to find all url nodes inside row nodes. Then, just append the parent node of each url element you find to a new DomDocument like so:
$xml = '...';
$dom = new DomDocument();
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xml);
$new_dom = new DomDocument();
$result = $new_dom->createElement('result');
$new_dom->appendChild($result);
$xpath = new DOMXPath($dom);
$rows = $xpath->query('//row/url');
for ($i=0;$i<$rows->length;$i++) {
$node = $new_dom->importNode($rows->item($i)->parentNode, TRUE);
$result->appendChild($node);
}
$new_dom->formatOutput = TRUE;
echo $new_dom->saveXML();
I'd use simplexml to read as your input, so your parsing would be easy. And then, i'd create a recursive function such as:
function isUrlElement($element){
foreach($element->children() as $children){
if($children->getName() == 'url'){
return true;
}else{
isUrlElement($children);
}
}
}
Now this is far from complete, but you could make it recursive calling it for each children. When this returns true, you'd know you found a node that has URL as a children. Use that $element node to for example add it to an array of simplexmlelements and then just foreach it back into XML.
Does that make sense?

How to parse a specific xml file using PHP simpleXML

I know there is already a lot of topics about simpleXML and PHP, but I need help with an specific xml code.
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
I need a foreach to get the data from each "product" like this:
<?
$feedUrl = 'url to xml file';
$rawFeed = file_get_contents($feedUrl);
$xml = simplexml_load_string($rawFeed);
foreach ($item ...????? ?)
{
}
How can I do this foreach to get the data. I tried all that I know without success.
Thanks.
First, you need <?xml version="1.0" encoding="UTF-8"?> as the first line in your XML, otherwise it's not valid. Then, and this will help you debug all sorts of things over your coding career, try this line:
echo "<pre>".print_r($xml,true)."</pre>";
That will give you the exact layout of the object you get back from the simplexml_load_string() call. From there, since you have a visual of the object layout, you should be able to figure out how to parse it. Incidentally, in your case, I think you'd need to do something like:
foreach($xml->vitrine as $element) {
// your code goes here
}
It seems PHP gets rid of evrything after the whitespace, because product id was changed to just product. Anyway here's the code.
<?php
$v = <<<ABC
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
ABC;
$xml = simplexml_load_string($v);
//print_r($xml);
foreach ($xml->product as $c){
echo $c->loja; //echoing out value of 'loja'
}
Outputs
ApetreXo.com
Fast Shop.com.b...

Categories