Przetwarzanie plików XML za pomocą php

Demo:
Gotowy skrypt można zobaczyć pod adresem: rss/xml/php

Nie od dziś wiadomo, że pliki XML są bardzo popularne i wykorzystywane przez strony internetowe, użytkowników, programistów, administratorów, itp. Co jakiś czas zachodzi potrzeba aby operować na plikach xml. Ja dzisiaj chciałem pokazać przykład wykorzystania plików xml za pomocą języka php, które generuje flickr. A dlaczego właśnie flickr? A no ponieważ mam tam mała kolekcję, a dodatkowo ładnie wygląda gotowy przetworzony plik xml właśnie z flickra, co możecie sami zaobserwować.
Układ xml ma ogólny jeden zarys, jednak różni się on detalami. Nie da się stworzyć uniwersalnego skryptu, który będzie w stanie przetworzyć i prawidłowo wyświetlić na ekranie wszystkie pliki xml. Jednak dla grup są one takie same, np. WordPress, czy omawiany flickr.

Pliki xml z flickr

Aby móc zacząć pracować na plikach xml, które oferuje flickr trzeba mieć odpowiedni adres. Dla każdego konta jest on unikatowy i można do niego dotrzeć poprzez swoje kont. Można to również sprawdzić nie mając konta, ale to już inna sprawa. No to mając już url prowadzący do naszego xml możemy podejrzeć co się pod nim kryje:
flickr-rss
jak widzimy widok ten nie jest zbyt estetyczny, no ale własnie taki ma być (podobno). Jest to zwykła lista z fotkami, nazwą oraz zdjęciem. Szaro-bure kolory sygnalizują, że mamy do czynienia z rss.
Każdy kto ma konto może sobie podejrzeć poprzez adres:

https://api.flickr.com/services/feeds/photos_public.gne?id='indywidualny-kod-dla-konta'

Będąc już na tej stronie możemy podejrzeć jak wygląda nasz plik xml, na którym będziemy operować. Wystarczy podejrzeć źródło strony.
Dla nas ważna jest struktura strony, bo to od niej zależy jakie zapytania użyć, aby móc operować na schemacie.

<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:creativeCommons="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html" xmlns:flickr="urn:flickr:user" version="2.0">
<channel>
<title>Uploads from CMB_Traveler</title>
<link>http://www.flickr.com/photos/99606293@N06/</link>
<description/>
<pubDate>Thu, 23 Oct 2014 06:27:33 -0700</pubDate>
<lastBuildDate>Thu, 23 Oct 2014 06:27:33 -0700</lastBuildDate>
<generator>http://www.flickr.com/</generator>
<image>...</image>
<item>...</item>
<item>...</item>
<item>...</item>
<item>...</item>
<item>...</item>

Początek jest mało ważny nas będzie głównie interesować to co znajduje się w znacznikach item. Jego struktura wygląda dla każdego tak samo:

<item>
<title>Forest...</title>
<link>
Forest...
</link>
<description>
<p><a href="http://www.flickr.com/people/99606293@N06/">CMB_Traveler</a> posted a photo:</p> <p><a href="http://www.flickr.com/photos/99606293@N06/14093716753/" title="Forest..."><img src="http://farm8.staticflickr.com/7370/14093716753_7acf7e67bb_m.jpg" width="240" height="180" alt="Forest..." /></a></p>
</description>
<pubDate>Wed, 30 Apr 2014 06:35:26 -0700</pubDate>
<dc:date.Taken>2014-04-30T15:34:50-08:00</dc:date.Taken>
<author flickr:profile="http://www.flickr.com/people/99606293@N06/">nobody@flickr.com (CMB_Traveler)</author>
<guid isPermaLink="false">tag:flickr.com,2004:/photo/14093716753</guid>
<media:content url="http://farm8.staticflickr.com/7370/14093716753_7acf7e67bb_b.jpg" type="image/jpeg" height="768" width="1024"/>
<media:title>Forest...</media:title>
<media:thumbnail url="http://farm8.staticflickr.com/7370/14093716753_7acf7e67bb_s.jpg" height="75" width="75"/>
<media:credit role="photographer">CMB_Traveler</media:credit>
</item>

Na tej podstawie będziemy tworzyć nasz skrypt.

Pobranie pliku xml przez php

Aby móc swobodnie pracować na xmlu musimy oczywiście pobrać jego zawartość do naszej strony. Robimy to poprzez:

$rss = new DOMDocument();
	$rss->load('http://api.flickr.com/services/feeds/photos_public.gne?id=99606293@N06&lang=en-us&format=rss_200');
	 $rss_info = simplexml_load_file('http://api.flickr.com/services/feeds/photos_public.gne?id=99606293@N06&lang=en-us&format=rss_200');

Funkcja DOMDocument() tworzy nam niejako nowy dokument HTML od podstaw.
Kolejno dwa razy wczytuje tą samą strukturę XML. Robię to dlatego, żeby pokazać, dwa warianty operowania na plikach. Zazwyczaj wystarczy raz to zaciągnąć.

Przetwarzanie danych XML

Jak już wyżej pisałem, mam zaciągnięte ten sam plik xml do dwóch różnych zmiennych. Na przykładzie $rss_info wyświetlę kilka danych z nagłówka rss.
Aby to dobrze zrobić trzeba się dokładnie przyjrzeć strukturze xml, oraz znacznikom, z których będziemy korzystać.

Wyświetlanie danych z XML za pomocą pętli foreach

<channel>
<title>Uploads from CMB_Traveler</title>
<link>http://www.flickr.com/photos/99606293@N06/</link>
<description/>
<pubDate>Thu, 23 Oct 2014 06:27:33 -0700</pubDate>
<lastBuildDate>Thu, 23 Oct 2014 06:27:33 -0700</lastBuildDate>
<generator>http://www.flickr.com/</generator>
<image>
<url>
http://farm4.staticflickr.com/3795/buddyicons/99606293@N06.jpg?1375266188#99606293@N06
</url>
<title>Uploads from CMB_Traveler</title>
<link>http://www.flickr.com/photos/99606293@N06/</link>
</image>

Przy takiej strukturze chcę wyciągnąć dane: adres obrazka, tytuł, link do strony.
Robię to przy pomocy funkcji foreach:

 foreach ($rss_info->channel->image as $info_page){
	echo '<div class="buddyico"><img src="'.$ico=$info_page->url.'"/></div>';	
	echo '<div class="main_title">'.$title=$info_page->title.'</div>';
	
	 echo '<div class="details"><span>Link do strony:</span> <a href='.$title=$info_page->link.'>'.$title=$info_page->link.'</a>';
 }

Warto szczególnie zwrócić uwagę na pierwszą linie:

$rss_info->channel->image as $info_page

Jak widać idzie ona dokładnie po znacznikach z naszej strony rss.

Wyświetlanie danych z XML za pomocą pętli for

Drugim sposobem (nie ostatnim oczywiście) jest pobranie danych i przetworzenie ich za pomocą pętli form. W pętli foreach do odnalezienia naszej ostatecznej ścieżki poruszaliśmy się po nazwach znaczników z pliku xml. W tym przykładzie będziemy dochodzić do naszych danych poprzez nazwy tagów: getElementsByTagName.
Zanim zaczniemy operować tworzymy funkcję DOM dla plików XML, oraz tablicę, do której będziemy wkładali nasze dane:

$rss2 = new DOMXPath($rss);
$feed = array();
$count = $rss2->evaluate('count(//item)'); //zliczanie elementów (item) na stronie

Nasza zmienna $count jest bardzo ważna, gdyż to od niej zależy jak długą nasze pętle będą wykonywać skrypt.
Mając już takie funkcję możemy stworzyć pętlę, for, która nie wyświetli żadnych elementów, ale wszystkie zapisze do tablicy $feed.

foreach ($rss->getElementsByTagName('item') as $my_item) {
		$item = array ( 
			'title' => $my_item->getElementsByTagName('title')->item(0)->nodeValue,
			'desc' => $my_item->getElementsByTagName('description')->item(0)->nodeValue,
			'link' => $my_item->getElementsByTagName('link')->item(0)->nodeValue,
			'date' => $my_item->getElementsByTagName('pubDate')->item(0)->nodeValue,
			);
		array_push($feed, $item);
	}

Pętla ta zaciągnęła dane dla tytułu, opisu, linka, oraz daty. Z nowych funkcji to pojawia nam się tutaj nodeValue. Zwraca ona wartość tekstową oraz wartość atrybutu. A więc mamy zwyczajny tekst z atrybutu.
Funkcja for wyświetli nam wszystkie elementy z tablicy $feed na ekranie (u mnie w formie listy ul li):

	echo '<ul class="lista">';
	for($x=0;$x<$count;$x++) {
		$title = str_replace(' & ', ' &amp; ', $feed[$x]['title']);
		$link = $feed[$x]['link'];
		$description = $feed[$x]['desc'];
		$date = date('Y/m/d', strtotime($feed[$x]['date']));
		echo '<li>';
		echo '<h2>Nazwa: </h2><a class="tit" href="'.$link.'" title="'.$title.'">'.$title.'</a>';
		echo '<p><h2>Data posta:</h2> '.$date.'</p>';
		preg_match ("/<img(.*?)>/is", $description, $znalezione);
		echo '<p class="img"><h2 class="pic">Zdjęcie: </h2>'.$znalezione[0].'</p>';
		
		echo '</li>';
	}

Zamiast kompletnego pola desc, które zawiera wiele innych mało istotnych elementów łowię wyłącznie zdjęcie poprzez wyrażenie regularne:

preg_match ("/<img(.*?)>/is", $description, $znalezione);

Do tego drobny css i możemy się chwalić naszym nowym rss’em.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

CAPTCHA
Change the CAPTCHA codeSpeak the CAPTCHA code