Blakes 21 Days Chapter 19 Document


Day 19, Reading and Writing RSS Feeds

Using XML

First Listing - Listing 19.1

Listing 19.1 - The Full Text of workbench.rss

An Explanation

Designing an XML Dialect

Processing XML with Java

Processing XML with XOM

Creating an XML Document

Listing 19.2 - The Full Text of feed.rss


Listing 19.3 - The Full Text of RssStarter.java

package com.java21days;

import java.io.*;
import nu.xom.*;

public class RssStarter {
    public static void main(String[] arguments) {
        // create an element to serve as the document's root
        Element rss = new Element("rss");

        // add a version attribute to the element
        Attribute version = new Attribute("version", "2.0");
        rss.addAttribute(version);
        // create a element and make it a child of
        Element channel = new Element("channel");
        rss.appendChild(channel);
        // create the channel's title tag with brackets
        Element title = new Element("title");
        Text titleText = new Text("Workbench");
        title.appendChild(titleText);
        channel.appendChild(title);
        // create the channel's link tag with brackets
        Element link = new Element("link");
        Text 1Text = new Text("http://workbench.cadenhead.org/");
        link.appendChild(1Text);
        channel.appendChild(link);

        // create a new document with as the root element
        Document doc = new Document(rss);

        // Save the XML document
        try (
            FileWriter fw = new FileWriter("feed.rss");
            BufferedWriter out = new BufferedWriter(fw);
        ) {
            out.write(doc.toXML());
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
        System.out.println(doc.toXML());
    }
}
564

Figure 19.1 - Creating an XML document with XOM. - goes here

560

Modifying an XML Document

Listing 19.4 - The Full Text of DomainEditor.java

package com.java21days;

import java.io.*;
import nu.xom.*;

public class DomainEditor {
    public static void main(String[] args) throws IOException {
        try (
            // create a tree from the XML document feed.rss
            Builder builder = new Builder();
            File xmlFile = new File("feed.rss");
            Document doc = builder.build(xmlFile);

            // get the root element rss
            Element root = doc.getRootElement();

            // get its channel element
            Element channel = root.getFirstChildElement("channel");

            // get its link element
            Element children = channel.getChildElements();
            for (int i = 0; i < children.size(); i++) {

                // get a link element
                Element link = children.get(i);

                // get its text
                Text linkText = (Text) link.getChild(0);

                // update any link matching a URL
                if (linkText.getValue().equals(
                    "http://workbench.cadenhead.org/")) {

                    // update the link's text
                    link.removeChild(0);
                    link.appendChild("http://www.cadenhead.org/");
                }
            }

            //create new elements and attributes to add
            Element item = new Element("item");
            Element itemTitle = new Element("title");

            //add them to the channel element
            itemTitle.appendChild(
                "Free the Bound Periodicals"
            item.appendChild(itemTitle);
            channel.appendChild(item);

            //Save the XML document
            try (
                FileWriter fw = new FileWriter("feed2.rss");
                BufferedWriter out = new BufferedWriter(fw);
            ) {
                out.write(doc.toXML());
            } catch (IOException ioe) {
                System.out.println(ioe.getMessage());
            }
            System.out.println(doc.toXML());
        } catch (ParsingException pe) {
            System.out.println("Parse error: " + pe.getMessage());
            pe.printStackTree());
            System.exit(-1);
        }
    }
}

Figure 19.2 - Loading and modifying an XML document. - goes here

568

Formatting an XML Document

Fifth Program - Listing 19.5 The Full Text of feed2.rss

Listing 19.6 The Full Text of DomainWriter.java

package com.java21days;

import java.io.*;
import nu.xom.*;

public class DomainWriter {
    public static void main(String[] args) throws IOException {
        try (
            // create a tree from an XML document
            // specified as a command-line argument
            Builder builder = new Builder();
            File xmlFile = new File("feed2.rss");
            Document doc = builder.build(xmlFile);

            // Create a comment with the current time and date
            Comment timestamp = new Comment("File created "
                + new java.util.Date());

            // Add the comment above everything else in the
            // document
            doc.insertChild(timestamp, 0);

            // Create a file output stream to a new file
            FileOutputStream f = new FileOutputStream("feed3.rss");

            // Using a serializer with indentation set as 2 spaces
            // write the XML document to the file
            Serializer output = new Serializer(f, "ISO-8859-1");
            output.setIndent(2);
            output.write(doc);

        } catch (ParsingException pe) {
            System.out.println("Parse error: " + pe.getMessage());
            pe.printStackTree());
            System.exit(-1);
        }
    }
}

Evaluating XOM

Listing 19.7 The Full Text of RssFilter.java


package com.java21days;

import nu.xom.*;

public class RssFilter {
    public static void main(String[] arguments) {

        if (arguments.length < 2) {
            System.out.println("Usage: java RssFilter file term");
            System.exit(-1);
        }

        // Save the RSS location and search term
        String rssFile = arguments[0];
        String term = arguments[1];

        try {
            // Fill a tree with an RSS file's XML data
            // The file can be local or something on the
            // Web accessible via a URL.
            Builder bob = new Builder();
            Document doc = bob.build(rssFile);

            // Get the file's root element ()
            Element rss = doc.getRootElement();

            // Get the element's version attribute
            Attribute rssVersion = rss.getAttribute("version");
            String version = rssVersion.getValue();

            // Add the DTD for RSS 0.91 feeds, if needed
            if ( (version.equals("0.91")) &
                (doc.getDocType() == null) ) {

                DocType rssDtd = new DocType("rss",
                    "http://my.netscape.com/publish/formats/rss-0.91.dtd");
                doc.insertChild(rssDtd, 0);
            }

            // Get the first (and only) element
            Element channel = rss.getFirstChildElement("channel");

            // Get its element
            Element title = channel.getFirstChildElement("title");
            Text titleText = (Text) title.getChild(0);

            // Change the title to reflect the search term
            titleText.setValue(titleText.getValue() + 
                ": Search for " + term + " articles");

            // Get all of the  elements and loop through them
            Elements items = channel.getChildElements("item");
            for (int i = 0; i < items.size(); i++) {
                // Get an item element
                Element item = items.get(i);

                // Look for a title element inside it
                Element iTitle = item.getFirstChildElement("title");

                // If found, look for its contents
                if (iTitle != null) {
                    Text iTitleText = (Text) iTitle.getChild(0);

                    // If the search text is not found in the item,
                    // delete it from the tree
                    if (iTitleText.toString().indexOf(term) == -1) {
                        channel.removeChild(item);
                    }
                }
            }

            // Display the results with a serializer
            Serializer output = new Serializer(System.out);
            output.setIndent(2);
            output.write(doc);
        } catch (Exception exc) {
            System.out.println("Error: " + exc.getMessage());
            exc.printStackTrace();
        }
    }
}

Figure 19.3 - Reading XML data from a website's RSS feed. - goes here

572

Summary

Q & A

Quiz - Questions

  1. What does RSS stand for ?
    1. Really Simple Syndication
    2. RDF Site Summary
    3. Both
  2. What method cannot be used to add text to an XML element using XOM ?
    1. addAttribute(String, String)
    2. appendChild(Text)
    3. appendChild(String)
  3. When all the opening element tags, closing element tags, and other markup are applied consistently in a document, what adjective describes the document ?
    1. Validating
    2. Parsable
    3. Well-formed

Answers

  1. C. One version, RSS 2.0 claims Really Simple Syndication as its name. The other, RSS 1.0 claims RDF Site Summary.
  2. A. Answers B and C both work. One adds the contents of a Text element as the element's character data, and the other adds the string.
  3. C. The data to be considered XML, it must be well-formed.

Certification Practice

  1. The NameDirectory class must be able to hold 20 different names. What statement should replace // answer goes here for the class to function correctly ?
    1. names[nameCount] = newName;
    2. names[nameCount] =+ newName;
    3. names[nameCount++] = newName;
    4. names[++nameCount] = newName;

Exercise