Thursday, July 29, 2010

xml 2: and now, a word from our compilers...


last time i demonstrated how to read xml data from a file, looking at the xml support in a few scripting languages. so that we might round out this discussion i will now show how to do the exact same thing with the exact same data using a handful of compiled languages. refer to my previous post to get the xml file and view what the program output should be.

the first language we'll look at is the one of the three that i am least familiar with: c#. despite the fact that i've never used the language outside the classroom and never written a line of “real” production code with it, this was the easiest to use. c# reads and writes much like the scripting languages we looked at last time.


1 // xmlsearch.cs
2
3 // Demonstrates how to parse data in an XML file using C-sharp's XPath
4 // implementation. The file is a collection of books, tech_books.xml.
5
6 using System;
7 using System.Xml;
8
9
10 class XmlSearch {
11
12 static void Main(string[] args) {
13 String separator = "- - - - - - - - - - - - - - - - - - - - - - - - -";
14 XmlDocument tree = new XmlDocument();
15 tree.Load("tech_books.xml");
16
17 // List all the books by title and author from the XML data.
18 XmlNodeList books = tree.SelectNodes("//publisher//book");
19 foreach(XmlNode book in books) {
20 Console.WriteLine("Title: {0}",
21 book.SelectSingleNode("title").InnerText);
22 if(book.SelectSingleNode("subtitle") != null) {
23 Console.WriteLine("Subtitle: {0}",
24 book.SelectSingleNode("subtitle").InnerText);
25 }
26 foreach(XmlNode author in book.SelectNodes("author")){
27 Console.WriteLine("Author: {0}", author.InnerText);
28 }
29 Console.WriteLine(separator);
30 }
31
32 // Get the ISBN and publisher for a book called "Writing Solid Code."
33 Console.WriteLine(separator);
34 String search = "Writing Solid Code";
35 foreach(XmlNode book in books) {
36 if(book.SelectSingleNode("title").InnerText == search) {
37 Console.WriteLine("{0} [{1}] published by {2}", search,
38 book.SelectSingleNode("isbn").InnerText,
39 book.ParentNode.Attributes["name"].Value);
40 }
41 }
42 Console.WriteLine(separator);
43 } // end method Main
44
45 } // end class XmlSearch
46

the next example is in java. while i have worked with java, i've never had to make it read xml before. i was a little disappointed. with factory classes and old-fashioned for loops it's more like c than c#.


1 /* XmlSearch.java
2 **
3 ** Demonstrates how to parse data in an XML file using Java's XPath API.
4 ** The file is a collection of books, tech_books.xml.
5 */
6
7 import javax.xml.parsers.*;
8 import javax.xml.xpath.*;
9 import org.w3c.dom.*;
10
11
12 public class XmlSearch {
13
14 public static void main(String[] args)
15 throws ParserConfigurationException, XPathExpressionException,
16 org.xml.sax.SAXException, java.io.IOException {
17
18 String separator = "- - - - - - - - - - - - - - - - - - - - - - - - -";
19 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
20 Document tree = factory.newDocumentBuilder().parse("tech_books.xml");
21 XPath xp = XPathFactory.newInstance().newXPath();
22
23 // List all the books by title and author from the XML data.
24 NodeList books = (NodeList)xp.evaluate("//publisher//book", tree,
25 XPathConstants.NODESET);
26 for(int i = 0; i < books.getLength(); i++) {
27 Node book = books.item(i);
28 System.out.printf("Title: %s\n",
29 xp.evaluate("title", book, XPathConstants.STRING));
30 if((xp.evaluate("subtitle", book, XPathConstants.NODE)) != null) {
31 System.out.printf("Subtitle: %s\n",
32 xp.evaluate("subtitle", book, XPathConstants.STRING));
33 }
34 NodeList authors = (NodeList)xp.evaluate("author", book,
35 XPathConstants.NODESET);
36 for(int j = 0; j < authors.getLength(); j++) {
37 System.out.printf("Author: %s\n",
38 authors.item(j).getTextContent());
39 }
40 System.out.println(separator);
41 }
42
43 // Get the ISBN and publisher for a book called "Writing Solid Code."
44 System.out.println(separator);
45 String search = "Writing Solid Code";
46 for(int i = 0; i < books.getLength(); i++) {
47 Node book = books.item(i);
48 if(search.equals(
49 xp.evaluate("title", book, XPathConstants.STRING))) {
50 System.out.printf("%s [%s] published by %s\n", search,
51 xp.evaluate("isbn", book, XPathConstants.STRING),
52 ((Element)book.getParentNode()).getAttribute("name"));
53 }
54 }
55 System.out.println(separator);
56 } // end method main
57
58 } // end class XmlSearch
59

for the sake of completeness, here is the code to do the same thing in c. i'm using libxml2 for its xdom and xpath capabilities. since this is a short example, i have simplified it by excluding all pointer and memory management. don't ever do that in real life. be sure to clean up after yourself: your parent object doesn't work here.


1 /* xmlsearch.c
2 *
3 * Demonstrates how to parse data in an XML file using LIBXML2 and XPath in C.
4 * The file is a collection of books, tech_books.xml.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <libxml/parser.h>
10 #include <libxml/xpath.h>
11
12
13 int main(int argc, char **argv) {
14 xmlDocPtr doc;
15 xmlXPathContextPtr tree;
16 xmlXPathObjectPtr result;
17 xmlNodeSetPtr nodeList;
18 xmlNodePtr book, cursor;
19 xmlChar *title, *subtitle, *author, *search, *isbn, *publisher;
20 char *separator = "- - - - - - - - - - - - - - - - - - - - - - - - -";
21 int found = 0;
22
23 doc = xmlParseFile("tech_books.xml");
24 tree = xmlXPathNewContext(doc);
25 result = xmlXPathEvalExpression((xmlChar *)"//publisher//book", tree);
26 nodeList = result->nodesetval;
27
28 // List all the books by title and author from the XML data.
29 for(int i = 0; i < nodeList->nodeNr; i++) {
30 book = nodeList->nodeTab[i];
31 cursor = book->xmlChildrenNode;
32 while(cursor != NULL) {
33 if((!xmlStrcmp(cursor->name, (xmlChar *)"title"))) {
34 title = xmlNodeListGetString(doc, cursor->xmlChildrenNode, 1);
35 printf("Title: %s\n", title);
36 }
37 if((!xmlStrcmp(cursor->name, (xmlChar *)"subtitle"))) {
38 subtitle = xmlNodeListGetString(doc,
39 cursor->xmlChildrenNode, 1);
40 printf("Subtitle: %s\n", subtitle);
41 }
42 if((!xmlStrcmp(cursor->name, (xmlChar *)"author"))) {
43 author = xmlNodeListGetString(doc, cursor->xmlChildrenNode, 1);
44 printf("Author: %s\n", author);
45 }
46 cursor = cursor->next;
47 }
48 puts(separator);
49 }
50
51 // Get the ISBN and publisher for a book called "Writing Solid Code."
52 puts(separator);
53 search = (xmlChar *)"Writing Solid Code";
54 result = xmlXPathEvalExpression((xmlChar *)"//publisher", tree);
55 nodeList = result->nodesetval;
56
57 for(int i = 0; i < nodeList->nodeNr; i++) {
58 cursor = nodeList->nodeTab[i];
59 publisher = xmlGetProp(cursor, (xmlChar *)"name");
60 book = cursor->xmlChildrenNode;
61 book = book->next;
62 while(book != NULL) {
63 cursor = book->xmlChildrenNode;
64
65 while(cursor != NULL) {
66 if((!xmlStrcmp(cursor->name, (xmlChar *)"title"))) {
67 title = xmlNodeListGetString(doc,
68 cursor->xmlChildrenNode, 1);
69 }
70 if((!xmlStrcmp(cursor->name, (xmlChar *)"isbn"))) {
71 isbn = xmlNodeListGetString(doc,
72 cursor->xmlChildrenNode, 1);
73 }
74 cursor = cursor->next;
75 }
76 if((!xmlStrcmp(title, search))) {
77 found = 1;
78 break;
79 }
80 book = book->next;
81 }
82 if(found) {
83 printf("%s [%s] published by %s\n", title, isbn, publisher);
84 break;
85 }
86 }
87 puts(separator);
88
89 return 0;
90 } // end method main
91

No comments:

Post a Comment