гиперссылки не работают, rss reader - PullRequest
0 голосов
/ 05 августа 2010

Привет, я пытаюсь создать RSS-ридер с использованием JavaScript. все работает, кроме гиперссылок. Мне нужно передать переменную, которая будет содержать URL для каждого элемента списка. Любой совет будет принят во внимание. Благодарю.

xml ---------------------------


    <?xml version="1.0"?>
    <rss version="2.0">
      <channel>
            <title>CNN RSS Feed</title>
        <link>http://rss.cnn.com/rss/cnn_world.rss</link>
        <description>Feeds from Army Public Affairs</description>
        <pubDate>Tue, 11 May 2010 22:04:03 GMT</pubDate>
        <language>en-us</language>

    <item>
            <title>U.S. ambassador to mark Hiroshima</title>
            <link>http://www.cnn.com/2010/WORLD/asiapcf/08/05/japan.us.hiroshima.presence/index.html?eref=rss_world&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+rss%2Fcnn_world+%28RSS%3A+World%29</link>
            <pubDate>June 24, 2010</pubDate>
            <source url="http://rss.cnn.com/rss/cnn_world.rss">CNN</source>
        </item>
        <item>
            <title>Study: Nearly 1.3 million Mexicans in capital don't have running water</title>

                    <link>http://www.cnn.com/2010/WORLD/americas/08/04/mexico.water.supply/index.html?eref=rss_world&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+rss%2Fcnn_world+%28RSS%3A+World%29</link>
            <pubDate>13 July 2010</pubDate>
            <source url="http://rss.cnn.com/rss/cnn_world.rss">CNN</source>

        </item> 


      </channel>
    </rss>

//JavaScript File 

    /OBJECTS

    //objects inside the RSS2Item object
    function RSS2Enclosure(encElement)
    {
        if (encElement == null)
        {
            this.url = null;
            this.length = null;
            this.type = null;
        }
        else
        {
            this.url = encElement.getAttribute("url");
            this.length = encElement.getAttribute("length");
            this.type = encElement.getAttribute("type");
        }
    }

    function RSS2Guid(guidElement)
    {
        if (guidElement == null)
        {
            this.isPermaLink = null;
            this.value = null;
        }
        else
        {
            this.isPermaLink = guidElement.getAttribute("isPermaLink");
            this.value = guidElement.childNodes[0].nodeValue;
        }
    }

    function RSS2Source(souElement)
    {
        if (souElement == null)
        {
            this.url = null;
            this.value = null;
        }
        else
        {
            this.url = souElement.getAttribute("url");
            this.value = souElement.childNodes[0].nodeValue;
        }
    }

    //object containing the RSS 2.0 item
    function RSS2Item(itemxml)
    {
        //required
        this.title;
        this.link;
        this.description;

        //optional vars
        this.author;
        this.comments;
        this.pubDate;

        //optional objects
        this.category;
        this.enclosure;
        this.guid;
        this.source;

        var properties = new Array("title", "link", "description", "author", "comments", "pubDate");
        var tmpElement = null;
        for (var i=0; i<properties.length; i++)
        {
            tmpElement = itemxml.getElementsByTagName(properties[i])[0];
            if (tmpElement != null)
                eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");
        }

        this.category = new RSS2Category(itemxml.getElementsByTagName("category")[0]);
        this.enclosure = new RSS2Enclosure(itemxml.getElementsByTagName("enclosure")[0]);
        this.guid = new RSS2Guid(itemxml.getElementsByTagName("guid")[0]);
        this.source = new RSS2Source(itemxml.getElementsByTagName("source")[0]);
    }

    //objects inside the RSS2Channel object
    function RSS2Category(catElement)
    {
        if (catElement == null)
        {
            this.domain = null;
            this.value = null;
        }
        else
        {
            this.domain = catElement.getAttribute("domain");
            this.value = catElement.childNodes[0].nodeValue;
        }
    }

    //object containing RSS image tag info
    function RSS2Image(imgElement)
    {
        if (imgElement == null)
        {
        this.url = null;
        this.link = null;
        this.width = null;
        this.height = null;
        this.description = null;
        }
        else
        {
            imgAttribs = new Array("url","title","link","width","height","description");
            for (var i=0; i<imgAttribs.length; i++)
                if (imgElement.getAttribute(imgAttribs[i]) != null)
                    eval("this."+imgAttribs[i]+"=imgElement.getAttribute("+imgAttribs[i]+")");
        }
    }

    //object containing the parsed RSS 2.0 channel
    function RSS2Channel(rssxml)
    {
        //required
        this.title;
        this.link;
        this.description;

        //array of RSS2Item objects
        this.items = new Array();

        //optional vars
        this.language;
        this.copyright;
        this.managingEditor;
        this.webMaster;
        this.pubDate;
        this.lastBuildDate;
        this.generator;
        this.docs;
        this.ttl;
        this.rating;

        //optional objects
        this.category;
        this.image;

        var chanElement = rssxml.getElementsByTagName("channel")[0];
        var itemElements = rssxml.getElementsByTagName("item");

        for (var i=0; i<itemElements.length; i++)
        {
            Item = new RSS2Item(itemElements[i]);
            this.items.push(Item);
            //chanElement.removeChild(itemElements[i]);
        }

        var properties = new Array("title", "link", "description", "language", "copyright", "managingEditor", "webMaster", "pubDate", "lastBuildDate", "generator", "docs", "ttl", "rating");
        var tmpElement = null;
        for (var i=0; i<properties.length; i++)
        {
            tmpElement = chanElement.getElementsByTagName(properties[i])[0];
            if (tmpElement!= null)
                eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");
        }

        this.category = new RSS2Category(chanElement.getElementsByTagName("category")[0]);
        this.image = new RSS2Image(chanElement.getElementsByTagName("image")[0]);
    }

    //PROCESSES

    //uses xmlhttpreq to get the raw rss xml
    function getRSS()
    {
        //call the right constructor for the browser being used
        if (window.ActiveXObject)
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        else if (window.XMLHttpRequest)
            xhr = new XMLHttpRequest();
        else
            alert("not supported");

        //prepare the xmlhttprequest object
        xhr.open("GET",document.rssform.rssurl.value,true);
        xhr.setRequestHeader("Cache-Control", "no-cache");
        xhr.setRequestHeader("Pragma", "no-cache");
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4)
            {
                if (xhr.status == 200)
                {
                    if (xhr.responseText != null)
                        processRSS(xhr.responseXML);
                    else
                    {
                        alert("Failed to receive RSS file from the server - file not found.");
                        return false;
                    }
                }
                else
                    alert("Error code " + xhr.status + " received: " + xhr.statusText);
            }
        }

        //send the request
        xhr.send(null);
    }

    //processes the received rss xml
    function processRSS(rssxml)
    {
        RSS = new RSS2Channel(rssxml);
        showRSS(RSS);
    }

    //shows the RSS content in the browser
    function showRSS(RSS)
    {
        //default values for html tags used
        var imageTag = "<img id='chan_image'";
        var startItemTag = "<div id='item'>";
        var startTitle = "<div id='item_title'>";
        var startLink = "<div id='item_link'>";
        var startDescription = "<div id='item_description'>";
        var endTag = "</div>";

        //populate channel data
        var properties = new Array("title","link","description","pubDate","copyright");
        for (var i=0; i<properties.length; i++)
        {
            eval("document.getElementById('chan_"+properties[i]+"').innerHTML = ''");
            curProp = eval("RSS."+properties[i]);
            if (curProp != null)
                eval("document.getElementById('chan_"+properties[i]+"').innerHTML = curProp");
        }

        //show the image
        document.getElementById("chan_image_link").innerHTML = "";
        if (RSS.image.src != null)
        {
            document.getElementById("chan_image_link").href = RSS.image.link;
            document.getElementById("chan_image_link").innerHTML = imageTag
                +" alt='"+RSS.image.description
                +"' width='"+RSS.image.width
                +"' height='"+RSS.image.height
                +"' src='"+RSS.image.url
                +"' "+"/>";
        }

        //populate the items
        document.getElementById("chan_items").innerHTML = "";
        for (var i=0; i<RSS.items.length; i++)
        {
            item_html = startItemTag;
            item_html += (RSS.items[i].title == null) ? "" : startTitle + RSS.items[i].title + endTag;
            item_html += (RSS.items[i].link == null) ? "" : startLink + RSS.items[i].link + endTag;
            item_html += (RSS.items[i].description == null) ? "" : startDescription + RSS.items[i].description + endTag;
            item_html += endTag;
            document.getElementById("chan_items").innerHTML += item_html;
        }

        //we're done
        //document.getElementById("chan").style.visibility = "visible";
        return true;
    }

    var xhr;

 <!-- html file -->

    <html>
    <head>
        <script language="javascript" src="rssajax.js"></script>
        <style type="text/css">
            #chan_items { margin: 20px; }
            #chan_items #item { margin-bottom: 10px; }
            #chan_items #item #item_title {
        font-weight: bold;
    }
        </style>
    </head>
    <body onload="getRSS()">

        <form name="rssform">
        <input name="rssurl" type="hidden" value="ChapRSS.xml">
    </form>


    <script language="javascript" src="rssajax.js"></script>

        <div class="rss" id="chan">
            <div id="chan_title"></div>

            <a href="chan_link" target="_blank" id="chan_link"></a>
            <div id="chan_description"></div>
            <div id="chan_image_link"></div>
            <a href="chan_image_link" target="_blank" id="chan_items"></a>
            <div id="chan_pubDate"></div>
            <div id="chan_copyright"></div>
        </div>
    </body>
    </html>

1 Ответ

1 голос
/ 05 августа 2010
<link>http://www.cnn.com/...?eref=rss_world&utm_source=...</link>

Это не правильно сформированный XML и, следовательно, не RSS.Вы должны экранировать все буквальные символы амперсанда в &amp;.

(Это также недопустимо в HTML. Когда вы помещаете & в атрибут href="...", вы также должны экранировать его в &amp;.Разница в том, что браузеры, как правило, исправляют вашу ошибку, а XML-парсеры - нет.

document.rssform.rssurl.value

Добавление идентификатора на <input> и использование document.getElementById менее двусмысленно, чем в старой школедоступ к коллекции форм.В любом случае, это довольно окольный способ получить значение в сценарии.Почему бы не потерять форму и просто передать имя файла RSS в качестве аргумента в getRSS()?

this.title;

Это ничего не делает вообще.Ни одно из мест, к которым вы относитесь к подобной собственности, не имеет никакого эффекта;вы не создаете членов, делая это.

var properties = new Array("title", "link", ...

В общем, избегайте конструктора new Array.Литеральный синтаксис массива (var properties= ['title', 'link, ...]; проще для чтения и не имеет неожиданного поведения конструктора для одного аргумента.

eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");

eval - зло. Никогда не используйте его.

Вы можете использовать квадратные скобки для доступа к свойству с динамическим именем. a.b совпадает с a['b'], поэтому:

this[properties[i]]= tmpElement.childNodes[0].nodeValue;

...

imgAttribs = new Array("url","title", ...

Вы не объявили var imgAttribs, так что это случайный глобал. То же самое с Item в RSS2Channel. (Почему заглавная буква?)

eval("this."+imgAttribs[i]+"=imgElement.getAttribute("+imgAttribs[i]+")");

Это не сработает из-за отсутствиякавычки на имени атрибута. Вы получите getAttribute(url), и нет переменной с именем url -> error. Опять же, используйте доступ к свойству в квадратных скобках, чтобы установить атрибут, а не eval.

eval("document.getElementById('chan_"+properties[i]+"').innerHTML = ''");

getElementById('chan_'+properties[i]) хорошо, нет смысла делать это в eval.

xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("Pragma", "no-cache");

Cache-Control и Pragma обычно являются полями ответа HTTP. Они не будут иметь эффектавы ожидаете в HTTP-запросе. Если вы хотите, чтобы на стороне клиента не происходило кэширование, используйте метод cachebuster, напримеркак добавление случайного числа или метки времени в строку запроса URL.

innerHTML = curProp

Опасность.Полученные вами значения являются произвольными текстовыми строками и могут содержать специальные символы HTML, такие как < и &.Если вы напишите такие строки в innerHTML элемента, вы, скорее всего, получите неработающие результаты, и если они содержат сторонний контент, вы только что дали себе дыру в безопасности межсайтового скриптинга.

Вы можетеиспользуйте textContent=..., чтобы установить содержимое элемента, не беспокоясь о экранировании HTML, однако затем вам необходимо определить, поддерживается ли он и вернуться к нестандартному свойству IE 1064 *, если это не так.Способ, который работает во всех браузерах, заключается в document.createTextNode(curProp) и добавлении этого текстового узла к элементу.

innerHTML= imageTag+" alt='"+RSS.image.description+ ...

У вас точно такая же проблема с экранированием HTML здесь: если, например,.описание содержит <script>, у вас проблемы.Вы можете написать HTML-кодировщик, например .:

function encodeHTML(s) {
    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}

innerHTML= imageTag+' alt="'+encodeHTML(RSS.image.description)+ ...

Но на самом деле создание HTML из кусочков строки - отстой.Вместо этого используйте методы DOM:

var img= document.createElement('img');
img.src= RSS.image.url;
img.title= RSS.image.description;
img.width= RSS.image.width;
img.height= RSS.image.height;
document.getElementById('chan_image_link').appendChild(img);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...