2016-12-01 16 views
0

Во-первых, у меня есть класс DOMParser;Как настроить мой DOMParser для анализа «медиа: контент» из RSS на Java (Android)?

import android.util.Log; 

import java.io.IOException; 
import java.io.StringReader; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 

import org.jsoup.Jsoup; 
import org.jsoup.select.Elements; 
import org.w3c.dom.Document; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.EntityResolver; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 

public class DOMParser { 

    private RSSFeed _feed = new RSSFeed(); 

    public RSSFeed parseXml(String xml) { 
     // _feed.clearList(); 
     URL url = null; 
     try { 
      url = new URL(xml); 
      Log.e("THE XML", xml); 
      Log.e("THE URL", url.toString()); 
     } catch (MalformedURLException e1) { 
      Log.e("MALFORMED EXCEPTION", "1"); 
      e1.printStackTrace(); 
     } 

     try { 
      // Create required instances 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      dbf.setValidating(false); 
      DocumentBuilder db = dbf.newDocumentBuilder(); 
      db.setEntityResolver(new EntityResolver() { 
       @Override 
       public InputSource resolveEntity(String arg0, String arg1) 
         throws SAXException, IOException { 
        if (arg0.contains("Hibernate")) { 
         return new InputSource(new StringReader("")); 
        } else { 
         // TODO Auto-generated method stub 
         return null; 
        } 
       } 
      }); 
      // Parse the xml 
      Document doc = db.parse(new InputSource(url.openStream())); 
      doc.getDocumentElement().normalize(); 

      // Get all <item> tags. 
      NodeList nl = doc.getElementsByTagName("item"); 
      int length = nl.getLength(); 

      for (int i = 0; i < length; i++) { 
       Node currentNode = nl.item(i); 
       RSSItem _item = new RSSItem(); 

       NodeList nchild = currentNode.getChildNodes(); 
       int clength = nchild.getLength(); 

       // Get the required elements from each Item 
       for (int j = 0; j < clength; j = j + 1) { 
        try { 
         Node thisNode = nchild.item(j); 
         String theString = null; 
         String nodeName = thisNode.getNodeName(); 
         Log.e("NODE NAME", nodeName); 
         theString = nchild.item(j).getFirstChild().getNodeValue(); 
         //Log.e("THE STRING", theString); 
         if (theString != null) { 
          if ("title".equals(nodeName)) { 
           // Node name is equals to 'title' so set the Node 
           // value to the Title in the RSSItem. 
           _item.setTitle(theString); 
          } else if ("description".equals(nodeName)) { 
           _item.setDescription(theString); 

           // Parse the html description to get the image url 
           String html = theString; 
           org.jsoup.nodes.Document docHtml = Jsoup 
             .parse(html); 
           Elements imgEle = docHtml.select("img"); 
           _item.setImage(imgEle.attr("src")); 
          } else if ("pubDate".equals(nodeName)) { 

           // We replace the plus and zero's in the date with 
           // empty string 
           String formatedDate = theString.replace(" +0000", 
             ""); 
           _item.setDate(formatedDate); 
          } else if ("link".equals(nodeName)) { 

           // Trying to get the URL as a string 
           _item.setURL(theString); 
          } 
         /*else if ("media:content".equals(nodeName)){ 
          _item.setImage(theString); 
          Log.e("THE IMAGE LINK", theString); 
         }*/ 

         } 
        } catch (Exception e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 

       // add item to the list 
       _feed.addItem(_item); 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     // Return the final feed once all the Items are added to the RSSFeed 
     // Object(_feed). 
     return _feed; 
    } 

} 
    } 

Я пытаюсь проанализировать записи, которые выглядят так:

<item> 
    <title><![CDATA[Oceans Full of 'Aliens' Could Be Hidden Beneath Earth's Surface, Expert Says]]></title> 
    <description><![CDATA[Do "aliens" exist on Earth? In a way, experts think so, and they believe that these creatures can be found thriving in massive underground oceans hidden hundreds of miles beneath the Earth's surface.]]></description> 
    <guid>http://www.natureworldnews.com/articles/33160/20161130/oceans-full-aliens-hidden-beneath-earths-surface-expert.htm</guid> 
    <link>http://www.natureworldnews.com/articles/33160/20161130/oceans-full-aliens-hidden-beneath-earths-surface-expert.htm</link> 
    <media:content url="http://images.natureworldnews.com/data/images/full/37450/earth-ocean.jpg" /> 
    <media:title type="html"><![CDATA[earth ocean]]></media:title> 
    <media:text type="html"><![CDATA[Do "aliens" exist on Earth? In a way, experts think so, and they believe that these creatures can be found thriving in massive underground oceans hidden hundreds of miles beneath the Earth's surface.]]></media:text> 
    <category> 
     <name><![CDATA[News]]></name> 
    </category> 
    <pubDate>Wed, 30 Nov 2016 11:02:00 EST</pubDate> 
</item> 
<item> 
    <title><![CDATA[Great Barrier Reef Sees Its Worst Damage on Record]]></title> 
    <description><![CDATA[The Great Barrier Reef is reportedly experiencing its worst damage via coral bleaching by far in history. The culprit is none other than the significant increase in water temperatures, which is record high as well. More than half of the coral population in the northern section has perished, while the central and southern centers have been reported to be in better health.]]></description> 
    <guid>http://www.natureworldnews.com/articles/33132/20161130/great-barrier-reef-sees-worst-damage-record.htm</guid> 
    <link>http://www.natureworldnews.com/articles/33132/20161130/great-barrier-reef-sees-worst-damage-record.htm</link> 
    <media:content url="http://images.natureworldnews.com/data/images/full/37433/great-barrier-reef-sees-its-worst-damage-on-record.jpg" /> 
    <media:title type="html"><![CDATA[Great Barrier Reef Sees Its Worst Damage on Record]]></media:title> 
    <media:text type="html"><![CDATA[Corals in the Great Barrier reef are in danger. 
]]></media:text> 
    <category> 
     <name><![CDATA[News]]></name> 
    </category> 
    <pubDate>Wed, 30 Nov 2016 09:54:00 EST</pubDate> 
</item> 

Пожалуйста, обратите внимание, что <media:content> тег - это где URL для изображений присутствуют.

Мой код бросает следующее для каждого отдельного входа в RSS! Может ли кто-нибудь объяснить значение #text, которое я вижу ниже? И может ли кто-нибудь помочь мне определить, как извлечь URL-адрес изображения и поместить его в метод setImage?

12-01 01:58:36.278 27776-27823/com.example01 E/NODE NAME: media:content 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String org.w3c.dom.Node.getNodeValue()' on a null object reference 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at com.climatenews07.parser.DOMParser.parseXml(DOMParser.java:74) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at com.climatenews07.SplashActivity$AsyncLoadXMLFeed.doInBackground(SplashActivity.java:103) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at com.climatenews07.SplashActivity$AsyncLoadXMLFeed.doInBackground(SplashActivity.java:97) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:304) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
12-01 01:58:36.278 27776-27823/com.example01 W/System.err:  at java.lang.Thread.run(Thread.java:761) 
12-01 01:58:36.278 27776-27823/com.example01 E/NODE NAME: #text 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String org.w3c.dom.Node.getNodeValue()' on a null object reference 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at com.climatenews07.parser.DOMParser.parseXml(DOMParser.java:74) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at com.climatenews07.SplashActivity$AsyncLoadXMLFeed.doInBackground(SplashActivity.java:103) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at com.climatenews07.SplashActivity$AsyncLoadXMLFeed.doInBackground(SplashActivity.java:97) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:304) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
12-01 01:58:36.279 27776-27823/com.example01 W/System.err:  at java.lang.Thread.run(Thread.java:761) 
12-01 01:58:36.279 27776-27823/com.example01 E/NODE NAME: media:title 

И из-за этого я также получаю следующее исключение;

12-01 01:58:36.500 27776-27927/com.example01 E/Image URL: http: 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err: java.net.UnknownHostException: Invalid host: http: 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.HttpUrl.getChecked(HttpUrl.java:670) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.OkHttpClient$1.getHttpUrlChecked(OkHttpClient.java:165) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.newHttpEngine(HttpURLConnectionImpl.java:345) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.initHttpEngine(HttpURLConnectionImpl.java:331) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:398) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:243) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.climatenews07.image.ImageLoader.getBitmap(ImageLoader.java:74) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.climatenews07.image.ImageLoader.access$000(ImageLoader.java:27) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at com.climatenews07.image.ImageLoader$PhotosLoader.run(ImageLoader.java:148) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
12-01 01:58:36.500 27776-27927/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
12-01 01:58:36.501 27776-27927/com.example01 W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
12-01 01:58:36.501 27776-27927/com.example01 W/System.err:  at java.lang.Thread.run(Thread.java:761) 

ответ

1

может кто-то помочь мне код, как извлечь URL изображения

Чтобы извлечь значение атрибута media:content элемента url:

import org.w3c.dom.Element; 
… 
if ("media:content".equals(nodeName)) { 
    Element contentElement = (Element) thisNode; 
    if (contentElement.hasAttribute("url")) { 
     String u = contentElement.getAttribute("url"); 
    } 
} 

Этот фрагмент кода бросает NodethisNode до Element, так что метод getAttribute(…) может затем используется для получения значения атрибута url.

Мой код бросает следующее для каждого входа в RSS!

Код в этом вопросе делает это:

theString = nchild.item(j).getFirstChild().getNodeValue(); 

... когда nchild.item(j) есть, например, это:

<media:content url="http://images.natureworldnews.com/data/images/full/37450/earth-ocean.jpg" /> 

Таким образом, в этом случае код вызывающего .getFirstChild() на media:content элемент, который не имеет детей, так что возвращает null. И тогда код вызывает .getNodeValue(), что приводит к ошибке java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String org.w3c.dom.Node.getNodeValue()' on a null object reference.

Кажется, что цель кода - получить значение атрибута url. Но атрибут не является дочерним, поэтому .getFirstChild() не получит атрибут url. Вместо этого следует использовать .getAttribute(…).

Может кто-то объяснить значение #text я вижу ниже

Каждый item элемент содержит не только дочерние элементы, но и текстовые узлы-из-за пространства между элементами. .getChildNodes() возвращает текстовые узлы вместе с узлами элементов.

Один из способов пропустить текстовые узлы есть в коде в цикле for, добавить что-то вроде этого:

if ("#text".equals(nodeName)) { 
    continue; 
} 
+0

Параметр 'СМИ: Content'' '/> синтаксис самозакрывающиеся-тегов (или [тэг empty-element] (https://www.w3.org/TR/REC-xml/#dt-empty), поскольку спецификация XML вызывает его) не является проблемой. Для парсера XML он точно такой же, как если бы он имел конечный тег. – sideshowbarker

+0

Вы пытались помещать 'if (« media: content ».equals (nodeName)) блок сразу после имени' Log.e («NODE NAME», nodeName); 'строка в вашем коде? Если вы это сделаете, это должно заставить его получить оценку, потому что выходной фрагмент в вопросе показывает, что он регистрирует «NODE NAME: media: content». – sideshowbarker

+0

Проблема была в том, что я проверял, было ли значение «theString» равно null перед фильтрацией имен узлов. Конечно, медиа: строка контента была нулевой. Извините, сейчас он работает. Благодарю. – Zac1