This example is to demonstrate how to modify a XML document. The Slashdot RSS feed is projected to this interface and the stories will be accessible via a subprojection. This time there is a setter for a collection of Stories which will replace the existing sequence of rss items. Instead of just setting an elements value like in the last example, we now change a sequence of elements. Notice that there are name spaces in the source XML document and that we work with them intuitively.
public interface SlashdotRSSFeed { /** * We like to access each story as a java object, so we define a sub * projection here. Notice that this does not have to be an inner interface, * thats just to compact this tutorial. */ interface Story { @XBRead("child::title") String getTitle(); @XBRead("child::pubDate") String getDate(); @XBRead("child::description") String getDescription(); } /** * Our getter method with an XPath expression to select all RSS items. The * target type definition specifies this getter as returning a list of sub * projections. * * @return List of all stories */ @XBRead("/rss/channel/item") List<Story> getAllItems(); /** * Our setter uses exact the same XPath expression as the getter. Thus it * will replace the items returned by getAllItems(). Notice that it will * only replace XML elements named "item", because that is exactly what the * XPath is selecting. Other child elements of the channel element won't be * touched. * * Notice that we could define another setter which could project a story to * other elements than "item" in the document hierarchy. * * @param items */ @XBWrite("/rss/channel/item") void setAllItems(Collection<Story> items); @XBRead("count(/rss/channel/item)") int getItemCount(); /** * This is not part of this lesson about modifying documents. Just to * demonstrate the flexibility of projections. There is no need to strictly * keep the object oriented way to the stories. We just define a getter for * all creator elements of all stories without a sub projection. * * Notice the seamless use of the namespace. The projector will use the * namespaces declared in the document. * * @return A list of all creators in this feed. */ @XBRead("//dc:creator") List<String> getCreators(); /** * Another getter not part of this lesson. This time we let the projection * declaration do some filtering. Usually you would have to code this in * java. * * @return A list of open source stories. */ @XBRead("/rss/channel/item[dc:subject=opensource]") List<Story> getOpenSourceStories();} |
And here some unit tests to print out some data about our RSS feed.
~~ This example is to demonstrate how to modify a XML document. The Slashdot RSS feed is projected to this interface and the stories will be accessible via a subprojection. This time there is a setter for a collection of Stories which will replace the existing sequence of rss items. Instead of just setting an elements value like in the last example, we now change a sequence of elements. Notice that there are name spaces in the source XML document and that we work with them intuitively.public class TestFilterRSSFeed extends TutorialTestCase{ private static SlashdotRSSFeed feed; @BeforeClass public static void readFeed() throws IOException { // XBProjector projector = new XBProjector(); // feed = projector.io().fromURLAnnotation(SlashdotRSSFeed.class); } @Ignore public void printSomeStats() { Set<String> creators = new HashSet<String>(feed.getCreators()); System.out.println("There are " + feed.getAllItems().size() + " stories by " + creators.size() + " different creators."); } /** * Remove all but the first three stories from a Slashdot RSS feed. Result * is formatted by standard Transformer capabilities. */ @Ignore //Slashdot changed the rss format recently. TODO: Need to think about a different examle. public void filterSomeArticles() throws IOException { List<Story> filteredItems = new LinkedList<Story>(); for (Story item : feed.getAllItems()) { filteredItems.add(item); if (filteredItems.size() == 3) { break; } } // This call removes all but the given items. Other child elements stay // untouched. feed.setAllItems(filteredItems); assertEquals(3,feed.getItemCount()); // System.out.println(feed.toString()); }} |