I am getting via simpleXML, the part of it here:
...
<channel id="Polo TV">
<display-name lang="pl">Polo TV</display-name>
<icon src="http://m-tvguide.pl/ikony/polo.png" />
<url>http://www.programtv.interia.pl</url>
</channel>
<programme start="20141030005500 +0100" stop="20141030015000 +0100" channel="TVP 1">
<title lang="pl">Po prostu</title>
<sub-title lang="pl">http://i.iplsc.com/-/0003K96AEV7D81JK-C0.jpg</sub-title>
...
<category lang="pl">Informacja</category>
<category lang="pl">Program Tomasza Sekielskiego</category>
</programme>
<programme start="20141030015000 +0100" stop="20141030033500 +0100" channel="TVP 1">
<title lang="pl">Dorwać małego</title>
...
more: http://wklej.to/2zmFZ .
My php script:
<?php
$xml=simplexml_load_file("file.xml");
$channels = array();
foreach ($xml->channel as $c) {
$channels[ $c['id']->__toString() ] = $c->{'display-name'}->__toString();
}
$time = date( "YmdHi" );
foreach($xml->xpath( 'programme[#channel="TVP"]' ) as $item) {
$start = substr( (string)$item["start"], 0, -8);
$end = substr( (string)$item["stop"], 0, -8);
if ($time > $start && $time < $end) {
echo "<b><font size='3'>$item->title </font></b><br>";
echo "<u><b>Gatunek:</b></u> ".$item->{'category'}. "<br>";
echo "<u><b>Start:</b></u> " .date("G:i", strtotime($start)) . '<br>';
echo "<u><b>Koniec:</b></u> " .date("G:i", strtotime($end)) . '<br>';
echo "<u><b>Kanał:</b></u> ".$channels[ $item["channel"]->__toString() ]. "<br>";
echo "<u><b>Opis:</b></u> ".$item->desc. "<br>";
}
}
?>
As it can be seen in xml file there are always two <category> directives provided. I want to get the second one instead of the first, as it is doing now.
If you have an array of elements, you can access them as you would elements in a standard PHP array, using a numeric subscript. It is best to check if the element is set first, though:
foreach($xml->xpath( 'programme[#channel="TVP"]' ) as $item) {
// code here...
# check whether the 'category' element is present
if (isset($item->category)) {
echo "<u><b>Gatunek:</b></u> ";
# check if there are two category items; if so, print the second
if (isset($item->category[1])) {
echo $item->category[1] . "<br>";
} else {
echo $item->category . "<br>";
}
}
// more code here...
}
Take the second category (they are zero-indexed) and if it does not exists, take the first one:
$item->category[1] ?: $item->category;
Related
I have the below code, which is displaying a calendar XML feed, however, not all events have a start/end time. This causes an error. I'd like for when an event does not have a start and end time, for it to display 'All Day' instead.
//load xml file
$sxml = simplexml_load_file($url) or die("Error: Cannot create object");
echo '<div class="calendar">';
#search for all event start dates
$starts = $sxml->xpath('//event/startdate');
#get the unique start dates of these event
$dates = array_unique($starts);
foreach($dates as $date) {
echo "<li><h1>{$date}</h1></li>" ."\n";
#search for all events taking place on each start date
$expression = "//event/startdate[.='{$date}']";
$events = $sxml->xpath($expression);
#iterate through these events and find their description
foreach ($events as $event){
echo "\t" , "<li><div class='time'>{$event->xpath('./following-sibling::starttime')[0]} - {$event->xpath('./following-sibling::endtime')[0]}</div><div class='event'><b> {$event->xpath('./following-sibling::description')[0]}</b> // {$event->xpath('./following-sibling::category')[0]}</div></li>";
echo "\n";
}
echo "\n";
}
echo "</div>";
Sample XML file below:
<event>
<startdate>24/11/2021</startdate>
<alldayevent>true</alldayevent>
<description>Event 1</description>
<category>Main Events</category>
</event>
<event>
<startdate>24/11/2021</startdate>
<alldayevent>false</alldayevent>
<starttime>14:00</starttime>
<endtime>16:30</endtime>
<description>Event 2</description>
<category>Main Events</category>
</event>
Expected Output:
If the event has a time/alldayevent = true then show start and end time, else if alldayevent = true, output 'All Day'
I believe, if I understand you correctly, you are looking for something like the following.
Change your foreach like this:
foreach($dates as $date) {
echo "<li><h1>{$date}</h1></li>" ."\n";
$expression = "//event/startdate[.='{$date}']";
$events = $sxml->xpath($expression) ;
foreach ($events as $event){
echo $event->xpath('.//following-sibling::description')[0]."\n";
if (($event->xpath('.//following-sibling::alldayevent'))[0] == "true") {
echo "\t" , "<li><div class='time'>All Day</div></li>" ."\n";
} else {
$st = $event->xpath('.//following-sibling::starttime')[0];
$et = $event->xpath('.//following-sibling::endtime')[0];
echo "\t" , "<li><div class='starttime'>$st</div></li>" ."\n";
echo "\t" , "<li><div class='endtime'>$et</div></li>" ."\n";
}
}
}
Output:
<li><h1>24/11/2021</h1></li>
Event 1
<li><div class='time'>All Day</div></li>
Event 2
<li><div class='starttime'>14:00</div></li>
<li><div class='endtime'>16:30</div></li>
I'm trying to get xml information from an url to be imported into mysql trough a php script, but I'm having some trouble and my experience dosen't cover this area.
The XML is formed as this example:
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:g="http://base.google.se/ns/1.0">
<channel>
<title></title>
<description></description>
<link></link>
<item>
<g:id></g:id>
<title></title>
<g:product></g:product>
</item>
<item>
<g:id></g:id>
<title></title>
<g:product></g:product>
</item>
and so on...
with the php script:
<?php
include '../connection-to-db.php';
$str_xml = file_get_contents('http://www.example.com/xmls/xmlfile.xml');
$library = new SimpleXMLElement($str_xml);
$arr = json_decode( json_encode($library) , true);
var_dump ($arr);
echo "Array got " .sizeof($arr['item']) . " items.<br> <br>";
if (sizeof($arr['item']) > 155555500) {
mysql_query("TRUNCATE TABLE google_stat");
$count = 0;
foreach ($arr['item'] as $shelf)
{
$gId = mysql_real_escape_string($shelf['g:id']);
$Title = mysql_real_escape_string($shelf['title']);
$gProductType = mysql_real_escape_string($shelf['g:product']);
mysql_query("INSERT INTO google_stat (gid, title, gcategory)
VALUES ('$gID', '$Title', '$gCategory')")
or die(mysql_error());
$count ++;
}
echo " Counted: " . $count . "inserts";
} else {
echo "Non counted, no insert done";
}
?>
Problem is when SimpleXMLElement it seems all items with g: in there names disappears when I look at the output, it dosen't even fint any items.
I've even tried with a localfile with same XML tree and can't even make that work.
I'm thankful for any help given, since I realize more and more I'm on deep water with this.
UPDATE:
<?php
include '../connection-to-db.php';
$str_xml = file_get_contents('http://www.example.com/xmls/xmlfile.xml');
$library = new SimpleXMLElement($str_xml);
$arr = json_decode( json_encode($library) , true);
echo "Array got " .sizeof($library->channel->item) . " items.<br> <br>";
if (sizeof($library->channel->item) > 100) {
mysql_query("TRUNCATE TABLE google_stat");
$count = 0;
foreach ($library->channel->item as $shelf)
{
$gId = (string) $shelf->children('g', TRUE)->id;
$Title = (string) $shelf->title;
$gProductType = $shelf->children('g', TRUE)->product;
echo $gId."<br />";
echo $Title."<br />";
echo $gProductType."<br />";
$count ++;
}
echo " Counted: " . $count . "inserts";
} else {
echo "Non counted, no insert done";
}
?>
Now I get the number of items in array, but $gId, $Title etc, dosen't echo any values.
Edit2: had to high array check, it works.
It has to do with the namespace prefix you want. You can access the g: items like so:
<?php
$str_xml = file_get_contents('test.xml');
$library = new SimpleXMLElement($str_xml);
$count = 0;
foreach ($library->channel->item as $shelf)
{
$gId = (string) $shelf->title;
$Title = (string) $shelf->children('g', TRUE)->id;
$gProductType = (string) $shelf->children('g', TRUE)->product;
echo $gId."<br />";
echo $Title."<br />";
echo $gProductType."<br />";
$count ++;
}
echo " Counted: " . $count . " inserts";
?>
See https://www.sitepoint.com/simplexml-and-namespaces/ for further reference.
xml.test
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:g="http://base.google.se/ns/1.0">
<channel>
<title>product</title>
<description>lots of products</description>
<link>www.example.com</link>
<item>
<g:id>ID 1</g:id>
<title>Title 1</title>
<g:product>Product 1</g:product>
</item>
<item>
<g:id>ID 2</g:id>
<title>Title 2</title>
<g:product>Product 2</g:product>
</item>
</channel>
</rss>
Output:
Title 1
ID 1
Product 1
Title 2
ID 2
Product 2
Counted: 2 inserts
I am having a hard time trying to understand why I can't compare the values of two arrays in PHP. If I echo both of these during the loop using "echo $description->ItemDesriptionName;" and "echo $item->ItemName;" the values seem to show as the same, but when I try to compare them using if, nothing works. What am I missing?
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
echo $item->ItemName . ' - ' . $item->Price . '</br>';
foreach ($itemdescription as $description) {
if ($description->ItemDescriptionName == $item->ItemName) {
echo 'We have a match!';
//where I would echo $description->ItemDescription;
}
}
}
?>
Here is the XML file
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Menu>
<Categories>
<Name>Category 1</Name>
<Items>
<ItemObject>
<ItemName>Item 1</ItemName>
<Price>1</Price>
</ItemObject>
<ItemObject>
<ItemName>Item 2</ItemName>
<Price>3</Price>
</ItemObject>
</Items>
</Categories>
<Options>
<Description>
<DescriptionObject>
<ItemDescriptionName>Item 1</ItemDescriptionName>
<ItemDescription>A Great item</ItemDescription>
</DescriptionObject>
<DescriptionObject>
<ItemDescriptionName>Item 2</ItemDescriptionName>
<ItemDescription>A Great item as well</ItemDescription>
</DescriptionObject>
</Description>
</Options>
</Menu>
</Root>
compare as string
and you have typo in ItemDescriptioName (ItemDescriptionName)
if ( (string)$description->ItemDescriptionName == (string)$item->ItemName) {
Convert to string and then compare
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$menu = $xml->Menu;
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
$itemname = $item->ItemName;
foreach ($itemdescription as $description) {
$descriptionname = $description->ItemDescriptionName ;
echo $itemname." ---- ".$descriptionname."<br/>";
if((string)$itemname === (string)$descriptionname){
echo "Yes its matched";
}
}
}
?>
Working fine for me
The properties like $description->ItemDescriptionName are SimpleXMLElement objects. So you do not compare strings but two objects.
SimpleXMLElement objects implement the magic method __toString(). They can be cast to string automatically, but a compare between to objects will not trigger that. You can force it:
if ((string)$description->ItemDescriptionName === (string)$item->ItemName) {
...
Can you access them directly instead using an accordant index?
...
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description;
$i = 0;
foreach ($items as $item) {
echo $i.' '.$item->ItemName . ' - ' . $item->Price;
echo $itemdescription->DescriptionObject[$i]->ItemDescriptionName[0];
echo ' ';
echo $itemdescription->DescriptionObject[$i]->ItemDescription[0];
echo '</br>';
$i++;
}
Hi I have been struggling with this puzzle for some time now how to get data out of this embedded namespaces here is the xml feed I have cut it down to make easier to read
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns="http://www.w3.org/2005/Atom" xmlns:sc="http://schemas.sage.com/sc/2009" xmlns:crm="http://schemas.sage.com/crmErp/2008" xmlns:sdatasync="http://schemas.sage.com/sdata/sync/2008/1" xmlns:sdata="http://schemas.sage.com/sdata/2008/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:sme="http://schemas.sage.com/sdata/sme/2007" xmlns:http="http://schemas.sage.com/sdata/http/2008/1">
<author />
<category term="tradingAccount" />
<generator />
<subtitle>Provides a feed containing tradingAccount details</subtitle>
<title>Sage Accounts 50 | tradingAccount - Practice Accounts </title>
<entry>
<author />
<content type="html"><![CDATA[<html>
</html>]]></content>
<id>http://computer_1:5493/sdata/accounts50/GCRM/{FF476636-D4AF-4191-BDE4-891EDA349A68}/tradingAccountCustomer(58b10585-63d4-4bb8-adb3-7096d9b055d9)?format=atomentry</id>
<link href="http://computer_1:5493/sdata/accounts50/GCRM/-/tradingAccountCustomer" rel="via" type="application/atom+xml" />
<published>2015-03-13T21:28:59.000+00:00</published>
<updated>2015-07-01T21:33:13.000+01:00</updated>
<http:httpStatus>200</http:httpStatus>
<sdata:payload>
<crm:tradingAccount sdata:url="http://computer_1:5493/sdata/accounts50/GCRM/{FF476636-D4AF-4191-BDE4-891EDA349A68}/tradingAccountCustomer(58b10585-63d4-4bb8-adb3-7096d9b055d9)?format=atomentry" sdata:uuid="58b10585-63d4-4bb8-adb3-7096d9b055d9">
<crm:active>true</crm:active>
<crm:customerSupplierFlag>Customer</crm:customerSupplierFlag>
<crm:companyPersonFlag>Company</crm:companyPersonFlag>
<crm:invoiceTradingAccount xsi:nil="true" />
<crm:openedDate>2013-04-22</crm:openedDate>
<crm:reference>AAA</crm:reference>
<crm:name>BBB</crm:name>
</crm:tradingAccount>
</sdata:payload>
</entry>
<opensearch:totalResults>118</opensearch:totalResults>
<opensearch:startIndex>1</opensearch:startIndex>
<opensearch:itemsPerPage>118</opensearch:itemsPerPage>
</feed>
I am trying to access the <crm:reference><crm:name><crm:openedDate> namespace but failing I have looked at similar projects but I think its a namespace within a namespace
here is my attempt at parsing the data
<?php
$xml = simplexml_load_file("sage.xml");
$xml->registerXPathNamespace('sdata', 'http://schemas.sage.com/sdata/sync/2008/1');
foreach($xml->xpath("//sdata:payload") as $entry) {
$entry->registerXPathNamespace('sdata', 'http://schemas.sage.com/sdata/sync/2008/1');
$entry->registerXPathNamespace('crm', 'http://schemas.sage.com/crmErp/2008');
$content = $entry->xpath("/sdata:payload/crm:tradingAccount/crm:active");
//$article = feed->xpath("/sdata:payload/crm:tradingAccount/crm:active");
foreach($content as $c) {
// echo $c->reference . " | " . $c->name . "/" . $c->accountOpenedDate . "<br />\n";
}
}
var_dump($content);
var_dump($c);
any pointers to my problem would help
foreach($xml->xpath("//sdata:payload") as $entry) {
// xpath here must be from payload to tradingAccount
$content = $entry->xpath("./crm:tradingAccount");
foreach($content as $c) {
// Make set of children with prefix crm
$nodes = $c->children('crm', true);
echo $nodes->reference . " | " . $nodes->name . " / " . $nodes->openedDate . "<br />\n";
}
}
It could be as simple as:
$xml = simplexml_load_file("sage.xml");
$reference = $xml->xpath("//crm:reference");
$name = $xml->xpath("//crm:name");
$openedDate = $xml->xpath("//crm:openedDate");
echo "reference: ". $reference[0] . "<br>";
echo "name: ". $name[0] . "<br>";
echo "openedDate: ". $openedDate[0] . "<br>";
If you would like to use a foreach loop to get all children of 'crm' you can do the following. You need atleast 5.2.0 if you want to set children to prefix (true)
$xml = simplexml_load_file("sage.xml");
foreach($xml->xpath("//crm:tradingAccount") as $entry) {
$child = $entry->children('crm', true);
}
echo "reference: ". $child->reference . "<br>";
echo "name: ". $child->name . "<br>";
echo "openedDate: ". $child->openedDate . "<br>";
My XMLfile is as follows:
<Project>
<ProjectInformation>
<FileHeader>IDGIS_PROJECT</FileHeader>
<Details ProjectID="0" ProjectName="" Description="" StartDate="02/05/2012 00:00:00 AM" OwnerShip="" LastModified="01/01/0001 00:00:00 AM" Datum="WGS_84" Projection="CYL" NoSignificantDecimals="3" ZoomCurrent="303601" RasterHeight="0" Background="-1">Project Details</Details>
<ProjectBounds XMin="25.4579486950873" YMin="44.7183808936148" XMax="26.5953949808977" YMax="45.5345534542584" ExtentBounds="no">Bounds</ProjectBounds>
</ProjectInformation>
<Layers>
<Layer ID="2" Description="" MinZoom="1" MaxZoom="1000000000" Visible="3" RemotHostType="LocalFile" RemotHost="" FolderName="Prahova_Highways" Path="" LayerStatus="ReadWrite">
</Layers>
I am unable to get child notes of Projectinformation. i want to get all attributes of Details and Project bounds. This thing is very easy in Java but i dunt know how to do it with php.
My code for getting childnotes of projectinformation is as follows:
$xmlDoc = new DOMDocument();
$xmlDoc->load('oglPrahova/prahova.GIS');
$x=$xmlDoc->documentElement;
var_dump($x);
$x = $xmlDoc->->getElementsByTagName('ProjectInformation');
foreach ($x->childNodes AS $item) {
print $i->nodeName . " = " . $item->nodeValue . "<br>";
}
You should use SimpleXML :
$xml = new SimpleXMLElement(
'<Project>
<ProjectInformation>
<FileHeader>IDGIS_PROJECT</FileHeader>
<Details ProjectID="0" ProjectName="" Description="" StartDate="02/05/2012 00:00:00 AM" OwnerShip="" LastModified="01/01/0001 00:00:00 AM" Datum="WGS_84" Projection="CYL" NoSignificantDecimals="3" ZoomCurrent="303601" RasterHeight="0" Background="-1">Project Details</Details>
<ProjectBounds XMin="25.4579486950873" YMin="44.7183808936148" XMax="26.5953949808977" YMax="45.5345534542584" ExtentBounds="no">Bounds</ProjectBounds>
</ProjectInformation>
<Layers>
<Layer ID="2" Description="" MinZoom="1" MaxZoom="1000000000" Visible="3" RemotHostType="LocalFile" RemotHost="" FolderName="Prahova_Highways" Path="" LayerStatus="ReadWrite" />
</Layers>
</Project>');
foreach($xml->ProjectInformation->Details->attributes() as $key => $value)
{
echo "$key : $value ";
}
foreach($xml->ProjectInformation->ProjectBounds->attributes() as $key => $value)
{
echo "$key : $value ";
}
As a more generic answer, you can use :
foreach($xml->ProjectInformation->children() as $child)
{
foreach($child->attributes() as $key => $value)
{
echo "$key : $value ";
}
}
You can also use xpath, as said in a comment.
Try with this.
$x = $xmlDoc->getElementsByTagName('ProjectInformation');
foreach ($x->childNodes as $nodename) {
if( $nodename->nodeName == 'FileHeader' ){
echo $nodename->nodeName. " - " . $nodename->nodeValue."<br>";
}
}
Where $nodename->nodeName holds all the child node names like FileHeader, Details, etc.