I want to get to foreach loops from the following xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<players>
<player id="1">4</player>
<player id="2">3</player>
</players>
<chats>
<chat playerid="2">Some chat here...</chat>
<chat playerid="1">skfgjh kjgh fdskgjhdf kgjhdf gkjd gkjdfhg dkfjhg</chat>
</chats>
</data>
I want one foreach with the players and one with the chats, but can't seem to figure this out... I also wants the attributes out and don't know how?
Here is what i have tried:
$userXML = simplexml_load_file('xml_chats/0^0.xml') or die ("error");
foreach($userXML->chats as $nchats){
echo $nchats->chat.'<br>';
}
What am I doing wrong and how can i achive this?
Thanks in advance :-)
You can try using the xpath method to select the nodes of your interest:
$xml = simplexml_load_string($xml);
$chats = $xml->xpath('/data/chats/chat');
$players = $xml->xpath('/data/players/player');
Or you can use the magic mapping of simplexml to nodes like this:
foreach ($xml->players->player as $player) { ... }
foreach ($xml->chats->chat as $chat) { ... }
Try like this
$xml=simplexml_load_file(filename);
foreach($xml->chats as $nchats){
foreach($nchats as $chat)
{
echo $nchats->chat.'<br>';
foreach($chat->attributes() as $key=>$attrib)
{
echo $key."=>".$attrib.'<br>';
}
}
}
Related
I need some assistance with the following issue. I have an xml file with the following structure:
<attributes>
<record ProductId="103" Compatibility="iPhone"/>
<record ProductId="103" Color="Black"/>
<record ProductId="103" Material="Leather"/>
<record ProductId="103" Collection="iPhone"/>
</attributes>
The problem is that I want to generate only one record per ProductId because it makes it easier for me to handle the information. The record should look like:
<record ProductId="103" Compatibility="iPhone" Color="Black" Material="Leather" Collection="iPhone"/>
I believe that using xpath is the way to go, but I just can't get the synthax right. I'm using a php script to parse the xml file.
Any assistance will be greatly appreciated.
Alternative you could just create a new one, but of course, get the necessary attributes first, gather them then apply them to the new one. Like this sample:
$xml_string = '<attributes><record ProductId="103" Compatibility="iPhone"/><record ProductId="103" Color="Black"/><record ProductId="103" Material="Leather"/><record ProductId="103" Collection="iPhone"/></attributes>';
$xml = simplexml_load_string($xml_string);
$record = new SimpleXMLElement('<attributes><record /></attributes>'); // create empty
$data = array();
foreach($xml->record as $entry) {
$attributes = $entry->attributes(); // get attributes
foreach($attributes as $key => $attribute) {
$data[$key] = (string) $attribute; // put it inside a container temporarily
}
}
// add the gathered attributes
foreach($data as $key => $value) {
$record->record->addAttribute($key, $value);
}
echo $record->asXML();
// echo htmlentities($record->asXML());
// <?xml version="1.0"?> <attributes><record ProductId="103" Compatibility="iPhone" Color="Black" Material="Leather" Collection="iPhone"/></attributes>
I am trying to get the PAY where it has the ID 3 Where it says the label phone
but i really dont know how, i tried everything.
Thanks for helping!
Here is the XML code:
$books = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data>
<login>1</login>
<arrStatsData>
<item>
<Id>500</Id>
<Label>website_name</Label>
<Data>
<item>
<Id>4</Id>
<Label>transactions</Label>
<Data>
<sum>2029.34</sum>
<cst>47.67575</cst>
<num>86</num>
<avg>23.6</avg>
<pay>1981.66</pay>
</Data>
</item>
<item>
<Id>3</Id>
<Label>Phone</Label>
<Data>
<sum>205</sum>
<cst>17.353</cst>
<num>205</num>
<avg>1</avg>
<pay>187.647</pay>
</Data>
</item>
......
PHP Code:
$xml = simplexml_load_string($arrResult); //load xml from above
foreach($xml->arrStatsData->item->Data as $item)
{
foreach($item->item as $DATA)
{
echo $DATA->Id.'<br>';
}
My result now is:
1981.66
187.647
-0.4448
Since you know some information that's tell the node apart from the rest you can use XPath to get the value directly instead of iterating through all of them:
<?php
$sxe = new SimpleXMLElement($books);
$pay = $sxe->xpath('//item[./Id=3]/Data/pay');
echo (string) $pay[0];
Ouput:
187.647
Your PHP code would be like this:
$xml = simplexml_load_string($books);
foreach($xml->arrStatsData->item->Data as $item)
{
//echo '$item;';
foreach($item->item as $DATA)
{
if($DATA->Id == '3'){
echo $DATA->Data->pay."<br/>";
}
}
}
It retrieve the pay value when the ID is equals to 3.
Rolando Isidoro was faster to recommend xpath, my solution is slightly different, that's why I post it, too:
$pay = (string)$xml->xpath("//item[Id = '3']/Data/pay")[0];
echo $pay;
see it working: http://codepad.viper-7.com/qzPlmp
ornek.xml here :
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book onay="e" katid="31" dil="tr">
<kitapadi>Dear Lovely</kitapadi>
<yazar>Author 1234</yazar>
<isbn>1234513</isbn>
</book>
<book onay="e" katid="32" dil="en">
<kitapadi>Love and Hate</kitapadi>
<yazar>Author 345</yazar>
<isbn>1234513</isbn>
</book>
</library>
PHP Code:
$xml = simplexml_load_file('veri/ornek.xml');
$search= '34';
$result = $xml->xpath('//yazar[contains(.,"'.$search.'")]');
foreach($result as $tt){
echo $tt;
}
If I use this, I can get the yazar attributes. But I want get another attributes
example:
$search = 34 where match yazar 34 giving this block in kitapadi,isbn,yazar
If you like to get the book containing a serach sring in yazar. Use something like this:
$xml = simplexml_load_file('veri/ornek.xml');
$search= "34";
$result = $xml->xpath("//book[yazar[contains(.,' $search')]]");
foreach($result as $tt){
echo $tt->isbn;
}
This XPath query does the trick:
//*[text()[contains(., '34')]]
Result:
Element='<yazar>Author 1234</yazar>'
Element='<isbn>1234513</isbn>'
Element='<yazar>Author 345</yazar>'
Element='<isbn>1234513</isbn>'
I am having an issue getting xml data in php
My xml is fairly complicated and there are several nested children in the tag.
xml
?xml version="1.0" encoding="UTF-8"?>
<book id="5">
<title id="76">test title</title>
<figure id="77"></figure>
<ch id="id78">
<aa id="80"><emph>content1</emph></aa>
<ob id="id_84" page-num="697" extra-info="4"><emph type="bold">opportunity.</emph></ob>
<ob id="id_85" page-num="697" extra-info="5"><emph type="bold">test data.</emph></ob>
<para id="id_86" page-num="697">2008.</para>
<body>
..more elements
<content>more contents..
</content>
</body>
</ch>
MY codes
//I need to load many different xml files.
$xml_file = simplexml_load_file($filename);
foreach ($xml_file->children() as $child){
echo $child->getName().':'. $child."<br>";
}
The codes above would only display
book, title, figure, ch but not the elements inside the ch tag. How do I display all the element inside each tag? Any tips? Thanks a lot!
Two things:
You need to match your <ob> </objective> tags.
Your foreach needs to be recursive. You should check if each item in your foreach has a child, then recursively foreach over that elements. I'd recommend using a separate function for this that you recursively call.
Example:
$xml_file = simplexml_load_file($filename);
parseXML($xml_file->children());
function parseXML($xml_children)
{
foreach ($xml_children as $child){
echo $child->getName().':'. $child."<br>";
if ($child->count() > 0)
{
parseXML($child->children());
}
}
}
You need to do resursive call
parseAllXml($xml_file);
function parseAllXml($xmlcontent)
{
foreach($xmlcontent->children() as $child)
{
echo $child->getName().':'. $child."<br>";
$is_further_child = ( count($child->children()) >0 )?true:false;
if( $is_further_child )
{
parseAllXml($child);
}
}
}
I have a document that it's structure is like below.
There are a lot of <entry>. My question is how can I output the <uri> of each entry? And another question, how can I output only the USERNAME?
This is the file I want to get the usernames http://search.twitter.com/search.atom?q=yankees
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:google="http://base.google.com/ns/1.0" xml:lang="en-US" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/" xmlns:georss="http://www.georss.org/georss">
<entry>
<author>
<name></name>
<uri>http://twitter.com/USERNAME</uri>
</author>
</entry>
<?php
$xml = new DOMDocument;
// link to ur file
$xml->load('');
foreach ($xml->getElementsByTagName('entry') as $product )
{
$append = array();
foreach($product->getElementsByTagName('uri') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
}
$result = $xml->saveXML();
print_r(str_replace('http://twitter.com/','',$result));
?>
You can use Xpath queries
http://www.php.net/manual/en/simplexmlelement.xpath.php
or
http://php.net/manual/en/domxpath.query.php
You should use SimpleXML some kind of a loop which goes trough all the s.
(foreach($xml->entry as $entry) loop should work fine, I think.)
And for the second: if it is always http://twitter.com/USERNAME, simply count the prefix's length than use a substr.
Resources to use: substr, SimpleXML, SimpleXML