Персональный проект RSS FEED XML Parser

Я относительно новичок в Java, и я пытался выяснить, как получить следующие теги для вывода в течение нескольких долгих, ДОЛГИХ дней. Я был бы очень признателен за понимание проблемы. Кажется, что все, что я мог найти или попробовать, просто не сработало. (извините за глупые новостные статьи)

<item>
<pubDate>Sat, 21 Sep 2013 02:30:23 EDT</pubDate>
<title>
<![CDATA[
Carmen Bryan Lashes Out at Beyonce Fans for Throwing Shade (@carmenbryan)
]]>
</title>
<link>
http://www.vladtv.com/blog/174937/carmen-bryan-lashes-out-at-beyonce-fans-for-throwing-shade/
</link>
<guid>
http://www.vladtv.com/blog/174937/carmen-bryan-lashes-out-at-beyonce-fans-for-throwing-shade/
</guid>
<description>
<![CDATA[
<img ... /><br />.
 <p>In response to someone who reminded Bryan that Jay Z has Beyonce now, she tweeted.</p>
 <p>Check out what else Bryan had to say above.</p>
 <p>Source: </p>
]]>
</description>
</item>

Мне удалось проанализировать XML и распечатать содержимое как в тегах элементов заголовка, так и в тегах описания, однако выходные данные для тега элемента описания также включают все его теги дочерних элементов. Я хотел бы использовать этот проект в будущем, чтобы расширить свое портфолио Java, пожалуйста, помогите!

Мой код до сих пор:

public class NewXmlReader
    {

        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
                try {

                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder builder = factory.newDocumentBuilder();
                        Document docXml = builder.parse(NewXMLReaderHandlers.inputHandler());
                        docXml.getDocumentElement().normalize();

                        NewXMLReaderHandlers.handleItemTags(docXml, "item");

                } catch (ParserConfigurationException | SAXException parserConfigurationException) {
                        System.out.println("You Are Not XML formated !!");
                        parserConfigurationException.printStackTrace();
                } catch (IOException iOException) {
                        System.out.println("URL NOT FOUND");
                        iOException.getCause();
                }
        }

    }

public class NewXMLReaderHandlers {

    private static int ARTICLELENGTH;

    public static String inputHandler() throws IOException {
        InputStreamReader inputStream = new InputStreamReader(System.in);
        BufferedReader bufferRead = new BufferedReader(inputStream);
        System.out.println("Please Enter A Proper URL: ");
        String urlPageString = bufferRead.readLine();
        return urlPageString;
    }

    public static void handleItemTags( Document document, String rssFeedParentTopicTag){
        NodeList listOfArticles = document.getElementsByTagName(rssFeedParentTopicTag);
        NewXMLReaderHandlers.ARTICLELENGTH = listOfArticles.getLength();
        String rootElement = document.getDocumentElement().getNodeName();
        if (rootElement == "rss"){
            System.out.println("We Have An RSS Feed To Parse");

            for (int i = 0; i < NewXMLReaderHandlers.ARTICLELENGTH; i++) {
                Node itemNode = (Node) listOfArticles.item(i);
                if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element itemElement= (Element) itemNode;
                    tagContent (itemElement, "title");
                    tagContent (itemElement, "description");
                }
            }
        }

    }

    public static void tagContent (Element item, String tagName) {
            NodeList tagNodeList = item.getElementsByTagName(tagName);
            Element tagElement = (Element)tagNodeList.item(0);
            NodeList tagTElist = tagElement.getChildNodes();
            Node tagNode = tagTElist.item(0);

//          System.out.println( " - " + tagName + " : " + tagNode.getNodeValue() + "\n");
            if(tagName == "description"){
                System.out.println( " - " + tagName + " : " + tagNode.getNodeValue() + "\n\n");
                System.out.println(" Do We Have Any Siblings? " + tagNode.getNextSibling().getNodeValue() + "\n");
            }
        }
    }

person Khalismatic    schedule 21.09.2013    source источник


Ответы (2)


За мои деньги самым простым решением было бы использование XPath API.

По сути, это язык запросов для XML. См. учебное пособие по XPath для начинающих.

В этом примере используется RSS-канал от SO, который использует <entry...> вместо <item>, но я использовал ту же технику для других файлов RSS (и XML) и даже для очень сложных документов HTML...

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class TestRSSFeed {

    public static void main(String[] args) {
        try {
            // Read the feed...
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            Document doc = factory.newDocumentBuilder().parse("http://stackoverflow.com/feeds/tag?tagnames=java&sort=newest");
            Element root = doc.getDocumentElement();

            // Create a xPath instance
            XPath xPath = XPathFactory.newInstance().newXPath();
            // Find all the nodes that are named <entry...> any where in
            // the document that live under the parent node...
            XPathExpression expression = xPath.compile("//entry");
            NodeList nl = (NodeList) expression.evaluate(root, XPathConstants.NODESET);

            System.out.println("Found " + nl.getLength() + " items...");
            for (int index = 0; index < nl.getLength(); index++) {
                Node node = nl.item(index);
                // This is a sub node search.
                // The search is based on the parent node and looks for a single
                // node titled "title" that belongs to the parent node...
                // I did this because I'm only expecting a single node...
                expression = xPath.compile("title");
                Node child = (Node) expression.evaluate(node, XPathConstants.NODE);
                System.out.println(child.getTextContent());
            }

        } catch (IOException | ParserConfigurationException | SAXException exp) {
            exp.printStackTrace();
        } catch (XPathExpressionException ex) {
            ex.printStackTrace();
        }
    }

}

Теперь вы можете выполнять довольно сложные запросы, но я решил начать с простого примера;)

person MadProgrammer    schedule 21.09.2013
comment
Это определенно намного проще реализовать, чем использовать обычный метод DOM. Я попробовал несколько комбинаций, но мне кажется, что я столкнулся с новой проблемой или с проблемой, которая у меня изначально была. Кажется, что проблема заключается в анализе любых подэлементов с CDATA в качестве родительского узла. Кажется, я просто не могу получить какую-либо информацию после ‹description›, то есть ‹![CDATA[‹img›‹br›‹p›‹/p›]]› не может быть пройден. Я пробовал анализировать подэлементы, но NodeList всегда оказывается пустым. Любые дополнительные предложения? - person Khalismatic; 24.09.2013
comment
Ничего себе, я ответил на свой вопрос! Еще раз спасибо за помощь MadProgrammer! - person Khalismatic; 26.09.2013
comment
Извините, хотел вернуться к вам, отвлекся :P - person MadProgrammer; 26.09.2013
comment
@MadProgrammer Огромное спасибо. Отличный ответ и в нужное время - person Vivek Aditya; 30.10.2015

На всякий случай, если кому-то все еще интересно, как мне удалось решить головоломку CDATA:

Логика следующая:

После того, как вы получите программу для извлечения всего xml для отображения правильного дерева узлов по мере отображения RSS-канала, если какие-либо данные xml заключены в теги CDATA, единственный способ получить доступ к этой информации — создать новый xml на основе текстового содержимого в тег CDATA. После того, как вы проанализируете новый документ, вы сможете получить доступ ко всем необходимым данным.

person Khalismatic    schedule 26.09.2013