QueryExample2 queries the Google Base data API, parses the result, and displays the titles of the returned data items.
One major problem with QueryExample1 is that it simply dumps
query results to the console, and the result is barely
readable. In any real life application the query result would need to be
parsed, interpreted, and the relevant information extracted and
displayed to the user. In QueryExample2 we demonstrate a
possible way of doing this by using a SAX parser to extract each data item's
title from the result and display it to the console. Some very basic
understanding of how SAX parsers work is necessary in order to fully
understand this example.
One might argue that for this task we don't even need a SAX parser. We
could just search for all <title> tags in the result and
display the characters that they enclose. Unfortunately, that wouldn't work,
as the Atom response also has a <title> tag, which is the
title of the feed:
<feed>
...
<title type="text">Items matching query: cars [item type : products]</title>
...
<entry>
...
<title type='text'>Great car for sale</title>
...
Atom does not mandate that the feed's <title> tag
should appear at a specific position inside the feed, so we need to make sure
we only display the <title> tags which are sub-elements of
an <entry> tag.
QueryExample2.java and fill in the DEVELOPER_KEY static string with your developer key. private static final String DEVELOPER_KEY = "";
javac com/google/api/gbase/examples/basic/QueryExample2.java java com/google/api/gbase/examples/basic/QueryExample2
The output will be as follows:
Item 1: Johnny Lightning MUSCLE CARS R8 1967 Chevelle SS Item 2: Johnny Lightning MUSCLE CARS USA 2005 Ford GT ... Item 25: The Cars movie Hinged tool Box Toy Organize lunch RARE
As in the previous example, we first send the query to the Google
Base data API server and obtain an inputStream containing the
response:
URL url = new URL(SNIPPETS_FEED + "?bq=" + URLEncoder.encode(QUERY, "UTF-8") + "&key=" + DEVELOPER_KEY); HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection(); InputStream inputStream = httpConnection.getInputStream();
We then use a standard SAX parser to parse the result. We obtain a SAXParser instance using a SAXParserFactory:
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser();
We then parse the resulting inputStream using DisplayTitlesHandler(), our custom SAX event handler:
parser.parse(inputStream, new DisplayTitlesHandler());
DisplayTitlesHandler() is derived from the no-op SAX parser, org.xml.sax.helpers.DefaultHandler. The logic inside DisplayTitlesHandler() is pretty simple: we keep a stack of the
currently open XML tags and print all character data when we are inside a <title> tag that has an <entry> parent. The insideEntryTitle flag is turned on each time we are inside an <entry><title> pair.
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("title") && xmlTags.peek().equals("entry")) {
insideEntryTitle = true;
System.out.print("Item " + ++itemNo + ": ");
}
xmlTags.push(qName);
Since startElement() is invoked each time the SAX parser
encounters an opening XML tag, we switch on insideEntryTitle only
if the currently parsed opening tag is <title> and the tag
on the top of the stack is <entry> . Here, we are also printing
the itemNo messages, rather than in the characters method, as characters can be called multiple times for different
chunks of the title's character data.
The endElement() method is invoked each time an XML tag closes.
All we need to do here is to remove the closing XML tag from the stack and,
if the removed XML tag was an entry's title, flip insideEntryTitle to false and go to a new line in the console
in preparation for printing out the next title.
public void endElement(String uri, String localName, String qName) throws SAXException {
xmlTags.pop();
if (insideEntryTitle) {
insideEntryTitle = false;
System.out.println();
}
}
The characters() method is invoked when the parser encounters
character data inside an XML element. If we are inside the <title> tag; that is, if the insideEntryTitle flag is on, we display the current characters: length characters
from the ch array, starting with start. As noted
earlier, we can't use println here to get to a new line, as characters can be invoked multiple times for different chunks of the
same title.
public void characters(char[] ch, int start, int length) throws SAXException {
if (insideEntryTitle) {
System.out.print(new String(ch, start, length));
}
}
In the main method, all we do is create an instance of QueryExample2 and invoke its displayItems() method.
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
new QueryExample2().displayItems();
}
Go to QueryExample3