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>
Related
I have a simple XML list with dates inside (chronological order). I have found a way loop the list 7 times (1 week).
<?php
$xmldata=simplexml_load_file("dates.xml");
$i = 0;
foreach($xmldata->day as $day) {
if($i==7) break;
$i++;
echo "<p>Date: " . $day->date . "</p>";
echo "<p>Dayname: " . $day->content . "</p>";
}
?>
Now I have the problem, that the loop always starts at the first line of the XML file and ends after 7 times. But I want to start the loop, when
$xmldata->day->date = $currentday;
$currentday = date('d.m.y');
and continue with the next 7 items (days) in the list.
The XML (dates.xml) looks like this:
<schedule>
<day>
<date>01.03.17</date>
<information>Lorem ipsum</information>
</day>
<day>
<date>02.03.17</date>
<information>Lorem ipsum</information>
</day>
<day>
<date>03.03.17</date>
<information>Lorem ipsum</information>
</day>
...
</schedule>
Thank you!
Solution after commnets:
<?php
$xmldata=simplexml_load_file("dates.xml");
$i = 0;
$startfound = false;
foreach($xmldata->day as $day) {
if(!$startfound && $day->date!=date('d.m.y')) continue;
$startfound = true;
if($i==7) break;
$i++;
echo "<p>Date: " . $day->date . "</p>";
echo "<p>Dayname: " . $day->content . "</p>";
}
?>
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;
I am trying to return twitter titles based on today's date only. I have made the following code below, but it returns every title no matter if its today's date or not.
$dom = new DOMDocument();
#$dom->loadHTMLFile('http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=google');
$xml = simplexml_import_dom($dom);
$twitter = $xml->xpath("//item");
foreach ($twitter as $item) {
$timezone = new DateTimeZone('America/Los_Angeles');
$date = new DateTime($item->pubdate);
$date->setTimeZone($timezone);
$twitter_date = $date->format("F j Y");
$todays_date = date("F j Y");
if ($twitter_date == $todays_date) {
foreach ($twitter as $item) {
$text = $item->title;
echo $text.'<br />';
}
}
}
You are looping again through EVERY $twitter inside the if statement. Try removing the foreach tag inside and just using the current $item:
if ($twitter_date == $todays_date) {
$text = $item->title;
echo $text.'<br />';
}
I have an rss feed that I am reading into. I need to retrieve certain data from the field in this feed.
This is the example feed data :
<content:encoded><![CDATA[
<b>When:</b><br />
Weekly Event - Every Thursday: 1:30 PM to 3:30 PM (CT)<br /><br />
<b>Where:</b><br />
100 West Street<BR>2nd floor<BR>Gainesville<BR>
<br>.....
How do I pull out the data for When: and Where: respectively? I attempted to use regex but I am unsure if I am not accessing the data correctly or if my regex expression is wrong. I'm not set on using regex.
This is my code:
foreach ($x->channel->item as $event) {
$eventCounter++;
$rowColor = ($eventCounter % 2 == 0) ? '#FFFFFF' : '#F1F1F1';
$content = $event->children('http://purl.org/rss/1.0/modules/content/');
$contents = $content->encoded;
echo '<tr style="background-color:' . $rowColor . '">';
echo '<td>';
//echo "<a id=buttonRed href='$event->link' title='$event->title' target='_blank'>" . $event->title . "</a>";
echo "" . $event->title . "";
echo '</td>';
echo '<td>';
$re = '%when\:\s*</b>\s*(.|\s)<br \/><br \/>$/i';
if (preg_match($re, $contents, $matches)) {
$date = $matches;
}
echo $date;
echo '</td>';
echo '<td>';
$re = '/^When\:<\/b>()$/';
if (preg_match($re, $contents, $matches)) {
$location = $matches;
}
echo $location;
echo '</td>';
echo '<td>';
echo "<a id=buttonRed href='$event->link' title='$event->title' target='_blank'>Click Here To Register</a>";
echo '</td>';
echo '</tr>';
}
The two $res are just my attempt to get the data out using different regex expressions. Let me know where I am going wrong. Thanks
The following should sort of get you there. (I wrote this from the top of my head and it does not exactly following your XML syntax. But you get the idea.)
<?php
$str = "<root><b>When:</b> whenwhen <b>Where:</b> wherewhere</root>";
$doc = new DOMDocument();
$doc->loadXML($str);
$when = $where = "";
$target = null;
foreach ($doc->documentElement->childNodes as $node) {
if ($node->tagName == "b") {
if (++$i == 1) {
$target = &$when;
} else {
$target = &$where;
}
}
if ($target !== null && $node->nodeType === XML_TEXT_NODE) {
$target .= $node->nodeValue;
}
}
var_dump($when, $where);
I had a problem like this and I ended up using YQL. Take a good look at the page-scraping code given there, especially the select command. Then go the the console and put in your own select statement, specifying the feed url and the xpath to the nodes you're wanting. Select JSON format. Then go down to the bottom of the page, get the REST query url, and use it in a jquery jsonp request. MAGIC!
please, don't extract data from XML-documents via regex.
The long answer is e.g. here: https://stackoverflow.com/a/335446/313145
The short answer is: it is not easier to use regex and will break often.
I'm embedding dates from google calendar into a website, and it's all working, with the exception of sorting. For some reason, it sorts into reverse-chronological order, when I'd really just like it to be normal chronological (first event first).
this is the output:
August 11th: Intern depart
August 6th: Last Day of Summer Camp
July 7th: Ignore this
July 6th: This is another example event
July 5th: example
June 28th: Summer Camp Starts
June 24th: Summer Pool Party
June 21st: Intern arrival date
June 15th: Assistant Director Arrival Date
June 14th: Director's training begins
May 26th: Brainstorm day for directors
I'm really still just learning a lot of this stuff- thanks for the help in advance!
<?php
$confirmed = 'http://schemas.google.com/g/2005#event.confirmed';
$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-d\Th:i:sP", time() - 172800);
$three_months_from_today = date("Y-m-d\Th:i:sP", time() + $three_months_in_seconds);
$feed = "http://www.google.com/calendar/feeds/qp6o02ka3iaoem2kr8odga6j7s%40group.calendar.google.com/" .
"public/full?orderby=starttime&singleevents=true&" .
"start-min=" . $three_months_ago . "&" .
"start-max=" . $three_months_from_today;
$doc = new DOMDocument();
$doc->load( $feed );
$entries = $doc->getElementsByTagName( "entry" );
foreach ( $entries as $entry ) {
$status = $entry->getElementsByTagName( "eventStatus" );
$eventStatus = $status->item(0)->getAttributeNode("value")->value;
if ($eventStatus == $confirmed) {
$titles = $entry->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
$times = $entry->getElementsByTagName( "when" );
$startTime = $times->item(0)->getAttributeNode("startTime")->value;
$when = date( "F jS", strtotime( $startTime ) );
$whentime = date( "g:ia", strtotime ( $startTime ) );
$places = $entry->getElementsByTagName( "where" );
$where = $places->item(0)->getAttributeNode("valueString")->value;
$links = $entry->getElementsByTagName( "link" );
$link = $links->item(0)->nodeValue;
print $when;
if ($whentime == "12:00am"){
;
}
else{
echo " at ";
print $whentime;
}
echo ": ";
echo "<b>";
print $title . "\n";
echo "</b>";
echo " ";
if(empty($where)){;}else{
echo "<br />";
print $where . "\n";
}
print $link;
print "<br />";
}
}
?>
Add &sortorder=descending to your feed URL. You can find documentation for this in the FAQ