]> git.wh0rd.org - tt-rss.git/blobdiff - classes/feedparser.php
fix support of Atom 0.3
[tt-rss.git] / classes / feedparser.php
index 274e871b9bef3f53df146d30585a1858df2bbe49..bd67ca39d9e7730e3390185e08ee19dffe490bc4 100644 (file)
@@ -6,6 +6,7 @@ class FeedParser {
        private $link;
        private $title;
        private $type;
+       private $xpath;
 
        const FEED_RDF = 0;
        const FEED_RSS = 1;
@@ -24,51 +25,120 @@ class FeedParser {
 
        function init() {
                $root = $this->doc->firstChild;
+               $xpath = new DOMXPath($this->doc);
+               $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
+               $xpath->registerNamespace('atom03', 'http://purl.org/atom/ns#');
+               $xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/');
+               $xpath->registerNamespace('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
+               $xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
+               $xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
+               $xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
+
+               $this->xpath = $xpath;
+
+               $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)")->item(0);
 
                if ($root) {
-                       switch ($root->tagName) {
-                       case "rss":
+                       switch (mb_strtolower($root->tagName)) {
+                       case "rdf:rdf":
+                               $this->type = $this::FEED_RDF;
+                               break;
+                       case "channel":
                                $this->type = $this::FEED_RSS;
                                break;
                        case "feed":
                                $this->type = $this::FEED_ATOM;
                                break;
                        default:
-                               $this->error = "Unknown/unsupported feed type";
+                               if( !isset($this->error) ){
+                                       $this->error = "Unknown/unsupported feed type";
+                               }
                                return;
                        }
 
-                       $xpath = new DOMXPath($this->doc);
-
                        switch ($this->type) {
                        case $this::FEED_ATOM:
-                               $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
 
                                $title = $xpath->query("//atom:feed/atom:title")->item(0);
 
+                               if (!$title)
+                                       $title = $xpath->query("//atom03:feed/atom03:title")->item(0);
+
+
                                if ($title) {
                                        $this->title = $title->nodeValue;
                                }
 
                                $link = $xpath->query("//atom:feed/atom:link[not(@rel)]")->item(0);
 
+                               if (!$link)
+                                       $link = $xpath->query("//atom03:feed/atom03:link[not(@rel)]")->item(0);
+
+
                                if ($link && $link->hasAttributes()) {
                                        $this->link = $link->getAttribute("href");
                                }
 
                                $articles = $xpath->query("//atom:entry");
 
+                               if (!$articles || $articles->length == 0)
+                                       $articles = $xpath->query("//atom03:entry");
+
                                foreach ($articles as $article) {
-                                       array_push($this->items, new FeedItem_Atom($article));
+                                       array_push($this->items, new FeedItem_Atom($article, $this->doc, $this->xpath));
                                }
 
                                break;
-                       case $this::FEED_RDF:
+                       case $this::FEED_RSS:
+
+                               $title = $xpath->query("//channel/title")->item(0);
+
+                               if ($title) {
+                                       $this->title = $title->nodeValue;
+                               }
+
+                               $link = $xpath->query("//channel/link")->item(0);
+
+                               if ($link && $link->hasAttributes()) {
+                                       $this->link = $link->getAttribute("href");
+                               }
+
+                               $articles = $xpath->query("//channel/item");
+
+                               foreach ($articles as $article) {
+                                       array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath));
+                               }
 
                                break;
-                       case $this::FEED_RSS:
+                       case $this::FEED_RDF:
+                               $xpath->registerNamespace('rssfake', 'http://purl.org/rss/1.0/');
+
+                               $title = $xpath->query("//rssfake:channel/rssfake:title")->item(0);
+
+                               if ($title) {
+                                       $this->title = $title->nodeValue;
+                               }
+
+                               $link = $xpath->query("//rssfake:channel/rssfake:link")->item(0);
+
+                               if ($link) {
+                                       $this->link = $link->nodeValue;
+                               }
+
+                               $articles = $xpath->query("//rssfake:item");
+
+                               foreach ($articles as $article) {
+                                       array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath));
+                               }
+
                                break;
+
+                       }
+               } else {
+                       if( !isset($this->error) ){
+                               $this->error = "Unknown/unsupported feed type";
                        }
+                       return;
                }
        }
 
@@ -98,4 +168,29 @@ class FeedParser {
                return $this->items;
        }
 
+       function get_links($rel) {
+               $rv = array();
+
+               switch ($this->type) {
+               case $this::FEED_ATOM:
+                       $links = $this->xpath->query("//atom:feed/atom:link");
+
+                       foreach ($links as $link) {
+                               if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
+                                       array_push($rv, $link->getAttribute('href'));
+                               }
+                       }
+                       break;
+               case $this::FEED_RSS:
+                       $links = $this->xpath->query("//channel/link");
+                       foreach ($links as $link) {
+                               if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
+                                       array_push($rv, $link->getAttribute('href'));
+                               }
+                       }
+                       break;
+               }
+
+               return $rv;
+       }
 } ?>