Processing Xml With Java - A Guide To Sax, Dom, Jdom, Jaxp, And Trax Free Open Book

Processing Xml With Java - A Guide To Sax, Dom, Jdom, Jaxp, And Trax

Previous Section Next Section

Writing XML

Now suppose you don't just want to dump out a bunch of raw numbers. Instead you want to produce a well-formed XML document, such as Example 3.2

Example 3.2 The First Ten Fibonacci Numbers in an XML Document
<?xml version="1.0"?>
<Fibonacci_Numbers>
  <fibonacci>1</fibonacci>
  <fibonacci>1</fibonacci>
  <fibonacci>2</fibonacci>
  <fibonacci>3</fibonacci>
  <fibonacci>5</fibonacci>
  <fibonacci>8</fibonacci>
  <fibonacci>13</fibonacci>
  <fibonacci>21</fibonacci>
  <fibonacci>34</fibonacci>
  <fibonacci>55</fibonacci>
</Fibonacci_Numbers>

To produce this, just add string literals for the <fibonacci> and </fibonacci> tags inside the print statements, as well as a few extra print statements to produce the XML declaration and the root element start- and end-tags. XML documents are just text, and you can output them any way you would output any other text document. Example 3.3 demonstrates

Example 3.3 A Program That Outputs the Fibonacci Numbers as an XML Document
import java.math.BigInteger;


public class FibonacciXML {

  public static void main(String[] args) {

      BigInteger low  = BigInteger.ONE;
      BigInteger high = BigInteger.ONE;

      System.out.println("<?xml version=\"1.0\"?>");
      System.out.println("<Fibonacci_Numbers>");
      for (int i = 0; i < 10; i++) {
        System.out.print("  <fibonacci>");
        System.out.print(low);
        System.out.println("</fibonacci>");
        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }
      System.out.println("</Fibonacci_Numbers>");

  }

}

Better Coding Practices

I'm going to keep the examples in this book as simple and small as I possibly can, and save my lines of code for the points that are relevant to XML. But don't use that as an excuse to forget all the good programming practices you've learned in the past, even if I don't use them here. For example, keeping too much data in string literals throughout the code makes a program very hard to localize and maintain. You may wish to move element names and other constants into final static fields, as shown in Example 3.4. You might even want to read the values of these variables from a resource bundle or system properties so they can be edited independently of the source code. I'm not going to do this here, because for purposes of education, it's more important to have short, self-contained examples that make the key points easy to grasp. However, in larger, more complex programs these techniques are essential.

Example 3.4 Using Named Constants for Element Names
import java.math.BigInteger;


public class FibonacciConstants {

  public final static String rootElementName
   = "Fibonacci_Numbers";
  public final static String fibonacciElementName = "fibonacci";
  public final static String xmlDeclaration
   = "<?xml version=\"1.0\"?>";

  public static void main(String[] args) {

      BigInteger low  = BigInteger.ONE;
      BigInteger high = BigInteger.ONE;

      System.out.println(xmlDeclaration);
      System.out.println("<" + rootElementName +">");
      for (int i = 0; i < 10; i++) {
        System.out.print("  <" + fibonacciElementName +">");
        System.out.print(low);
        System.out.println("</" + fibonacciElementName +">");
        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }
      System.out.println("</" + rootElementName +">");

  }

}

Attributes

Now let's suppose you want to add some attributes to the elements. For instance, you might want to give each fibonacci element an index attribute specifying which Fibonacci number it is (the first, the second, the third, and so forth). To do this, you would simply add the extra strings to the source code and calculate the index value from the loop index. Example 3.5 demonstrates.

Example 3.5 A Java Program That Writes an XML Document Which Uses Attributes
import java.math.BigInteger;


public class FibonacciAttributes {

  public static void main(String[] args) {

      BigInteger low  = BigInteger.ONE;
      BigInteger high = BigInteger.ONE;

      System.out.println("<?xml version=\"1.0\"?>");
      System.out.println("<Fibonacci_Numbers>");
      for (int i = 1; i <= 10; i++) {
        System.out.print("  <fibonacci index=\"" + i + "\">");
        System.out.print(low);
        System.out.println("</fibonacci>");
        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }
      System.out.println("</Fibonacci_Numbers>");

  }

}

The only even remotely difficult part of this is realizing you have to escape the double quotes used to delimit the attribute values as \" in the Java source code. An alternative is to use single quotes to delimit the attribute values. These don't need to be escaped inside Java string literals. For example,

System.out.print("  <fibonacci index='" + i + "'>"); 

Following is the output from Example 3.5:

<?xml version="1.0"?> 
<Fibonacci_Numbers>
  <fibonacci index="1">1</fibonacci>
  <fibonacci index="2">1</fibonacci>
  <fibonacci index="3">2</fibonacci>
  <fibonacci index="4">3</fibonacci>
  <fibonacci index="5">5</fibonacci>
  <fibonacci index="6">8</fibonacci>
  <fibonacci index="7">13</fibonacci>
  <fibonacci index="8">21</fibonacci>
  <fibonacci index="9">34</fibonacci>
  <fibonacci index="10">55</fibonacci>
</Fibonacci_Numbers>

Producing Valid XML

So far the Java programs have produced XML documents that were well formed but not valid. Making them valid is not difficult. Simply print a document type declaration that either includes an internal DTD subset or points to an appropriate external DTD subset. Example 3.6 takes the internal subset approach.

Example 3.6 A Java Program That Generates a Valid Document
import java.math.BigInteger;


public class ValidFibonacci {

  public static void main(String[] args) {

      BigInteger low  = BigInteger.ONE;
      BigInteger high = BigInteger.ONE;

      System.out.println("<?xml version=\"1.0\"?>");
      System.out.println("<!DOCTYPE Fibonacci_Numbers [");
      System.out.println(
       "  <!ELEMENT Fibonacci_Numbers (fibonacci)*>");
      System.out.println("  <!ELEMENT fibonacci (#PCDATA)>");
      System.out.println(
       "  <!ATTLIST fibonacci index NMTOKEN #REQUIRED>");
      System.out.println("]>");
      System.out.println("<Fibonacci_Numbers>");
      for (int i = 0; i < 10; i++) {
        System.out.print("  <fibonacci index=\"" + i + "\">");
        System.out.print(low);
        System.out.println("</fibonacci>");
        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }
      System.out.println("</Fibonacci_Numbers>");

  }

}

Following is the output from this program, including the document type declaration:

<?xml version="1.0"?> 
 <!DOCTYPE Fibonacci_Numbers [
   <!ELEMENT Fibonacci_Numbers (fibonacci)*>
   <!ELEMENT fibonacci (#PCDATA)>
   <!ATTLIST fibonacci index NMTOKEN #REQUIRED>
 ]>
 <Fibonacci_Numbers>
   <fibonacci index="0">1</fibonacci>
   <fibonacci index="1">1</fibonacci>
   <fibonacci index="2">2</fibonacci>
   <fibonacci index="3">3</fibonacci>
   <fibonacci index="4">5</fibonacci>
   <fibonacci index="5">8</fibonacci>
   <fibonacci index="6">13</fibonacci>
   <fibonacci index="7">21</fibonacci>
   <fibonacci index="8">34</fibonacci>
   <fibonacci index="9">55</fibonacci>
 </Fibonacci_Numbers>

Attaching a schema is no harder. Just place the necessary xmlns:xsi and xsi:noNamespaceSchemaLocation attributes on the root element.

Namespaces

Suppose that instead of using a custom Fibonacci number vocabulary, you wanted to use the standard MathML vocabulary, as shown in Example 3.7. The element names all have prefixes, and an xmlns:mathml attribute on the root element binds the mathml prefix to the http://www.w3.org/1998/Math/MathML namespace URI. Each Fibonacci number is included in a mathml:mrow divided into a mathml:mi element, a mathml:mo element, and a mathml:mn element.

Example 3.7 A MathML Document That Contains Fibonacci Numbers
<?xml version="1.0"?>
<mathml:math xmlns:mathml="http://www.w3.org/1998/Math/MathML">
  <mathml:mrow>
    <mathml:mi>f(1)</mathml:mi>
    <mathml:mo>=</mathml:mo>
    <mathml:mn>1</mathml:mn>
  </mathml:mrow>
  <mathml:mrow>
    <mathml:mi>f(2)</mathml:mi>
    <mathml:mo>=</mathml:mo>
    <mathml:mn>1</mathml:mn>
  </mathml:mrow>
  <mathml:mrow>
    <mathml:mi>f(3)</mathml:mi>
    <mathml:mo>=</mathml:mo>
    <mathml:mn>2</mathml:mn>
  </mathml:mrow>
  <mathml:mrow>
    <mathml:mi>f(4)</mathml:mi>
    <mathml:mo>=</mathml:mo>
    <mathml:mn>3</mathml:mn>
  </mathml:mrow>
</mathml:math>

The markup is somewhat more complex, but the Java code is not significantly more so, as Example 3.8 demonstrates.

Example 3.8 A Java Program That Generates a MathML Document
import java.math.BigInteger;


public class MathMLFibonacci {

  public static void main(String[] args) {

      BigInteger low  = BigInteger.ONE;
      BigInteger high = BigInteger.ONE;

      System.out.println("<?xml version=\"1.0\"?>");
      System.out.println(
        "<mathml:math "
        + "xmlns:mathml=\"http://www.w3.org/1998/Math/MathML\">"
      );
      for (int i = 1; i <= 10; i++) {
        System.out.println("  <mathml:mrow>");
        System.out.println("    <mathml:mi>f(" + i
         + ")</mathml:mi>");
        System.out.println("    <mathml:mo>=</mathml:mo>");
        System.out.println("    <mathml:mn>" + low
         + "</mathml:mn>");
        System.out.println("  </mathml:mrow>");
        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }
      System.out.println("</mathml:math>");

  }

}

I could continue, showing you how to add comments, processing instructions, CDATA sections, and other features of XML; but I think by now you're getting the idea. XML documents are just text. They can be represented inside Java programs as various combinations of String literals and String variables. Other data types such as int and BigInteger can be converted to their string representations, either implicitly by concatenating them with strings, or explicitly by invoking methods such as toString() and String.valueOf(). The fact that XML documents are text makes it very easy to organize XML output this way.

When you use this technique, you are responsible for following all the well-formedness, namespace well-formedness, and validity rules of XML. Nothing prevents you from producing incorrect XML. In fact, your first few efforts are likely to be malformed. You'll want to run your output through a tool such as Xerces-J's sax.Counter to check it for well-formedness and perhaps validity. Making sure the output is correct is simply one part of testing and debugging your code. The same would be true if you were outputting a non-XML format. In fact, if anything, XML makes these tests easier because it's straightforward to write declarative schemas that express exactly what is and is not legal, and to compare your output against these schemas.

Eventually we'll take up some alternatives to the direct string approach such as DOM and JDOM that do enable you to automatically maintain well-formedness and sometimes even validity. However, for many simple cases, these are vast overkill. It can be much simpler to just write a few strings onto an output stream. In the next section, we'll look at how you can change the characteristics of the output stream you're writing on.

    Previous Section Next Section


         Main Menu
    Main Page
    Table of content
    Copyright
    Praise for Elliotte Rusty Harold's 'Processing XML with Java™'
    List of Examples
    List of Figures
    Preface
    Part I: XML
    Chapter 1. XML for Data
    Chapter 2. XML Protocols: XML-RPC and SOAP
    Chapter 3. Writing XML with Java
    Fibonacci Numbers
    Writing XML
    Output Streams, Writers, and Encodings
    A Simple XML-RPC Client
    A Simple SOAP Client
    Servlets
    Summary
    Chapter 4. Converting Flat Files to XML
    Chapter 5. Reading XML
    Part II: SAX
    Part III: DOM
    Part IV: JDOM
    Part V: XPath/XSLT
    Part VI: Appendixes


    More Books
    PHP Hacks
    Processing Xml With Java - A Guide To Sax, Dom, Jdom, Jaxp, And Trax
    The Koran (Holy Qur'an)
    Macromedia Flash 8 Bible
    Search Engine Optimization for Dummies
    YouTube Traffic
    PHP 5 for Dummies
    Harry Potter and The Chamber of Secrets
    Harry Potter and the Sorcerer's Stone
    The Pilgrim's Progress
    Wireless Hacks
    Flash Hacks. 100 Industrial-Strength Tips & Tools
    PayPal Hacks. 100 Industrial-Strength Tips and Tools
    Amazon Hacks
    Pdf Hacks
    The Da Vinci Code
    Google Hacks
    The Holy Bible
    Windows XP For Dummies
    Harry Potter and the Half-Blood Prince
    Seo Book
    Upgrading and Repairing Networks
    Macromedia Dreamweaver 8 UNLEASHED
    Windows XP Annoyances
    Windows XP Hacks
    Microsoft Windows XP Power Toolkit
    Teach Yourself MS Office In 24Hours
    iPod & iTunes Missing Manual
    PC Hacks 100 Industrial-Strength Tips and Tools
    PC Overclocking, Optimization, and Tuning - 2th Edition
    PC Hardware In A Nutshell 3rd Edition
    PC Hardware in a Nutshell, 2nd Edition
    Upgrading and Repairing PCs
    Google for Dummies
    MySQL Cookbook
    Teach Yourself Macromedia Flash 8 In 24 Hours
    PHP CookBook
    Sams Teach Yourself JavaScript in 24 Hours
    PHP5 Manual
    Free Games Paper Airplanes
    500 Juegos Gratis 500 Giochi Gratis 500 Jeux Gratuits 500 Jogos Gratis 500 Kostenlose Spiele