SAX writer

Vance Christiaanse vance at textwise.com
Tue Jul 27 20:35:39 BST 1999


Mark Cheek wrote in part:

> ...  I now need to serialize my new Document object to
> disk as an xml file.  I cannot find any DOM classes or methods to do
> this.. can anyone help?  I do not want to use IBM's or Sun's DOMWriter
> classes as we are not sure yet which parser library we are going to
> implement.

Paragraph 1.1 of the Level 1 DOM spec actually states that its scope
does not include persistent storage of a Document. I needed to do what
you want to do and I just took the code from within DOMWriter.java. The
main change I made was passing "canonical" as a parameter instead of
letting it be a global variable. This code should work with any
DOM-compliant classes, not just XML4J.

Vance

Vance Christiaanse
TextWise, LLC
vance at textwise.com


   /*************************************************************
    * Prints the specified node, recursively.
    *
    * This code was adapted from the sample code "DOMWriter.java"
    * included with XML4J.
    ************************************************************/

   public static void print(PrintWriter out, boolean canonical, Node
node) {

      //-------------------------
      // Is there anything to do?
      //-------------------------

      if (node == null) {
         return;
      }

      int type = node.getNodeType();
      switch (type) {

         //----------------
         // Print document.
         //----------------

         case Node.DOCUMENT_NODE: {
            if (!canonical) {
               out.println("<?xml version=\"1.0\"
encoding=\"UTF-8\"?>");
            }
            print(out, canonical,
((Document)node).getDocumentElement());
            out.println();
            out.flush();
            break;
         }

         //-------------------------------
         // Print element with attributes.
         //-------------------------------

         case Node.ELEMENT_NODE: {
            out.print('<');
            out.print(node.getNodeName());
            Attr attrs[] = sortAttributes(node.getAttributes());
            for (int i = 0; i < attrs.length; i++) {
               Attr attr = attrs[i];
               out.print(' ');
               out.print(attr.getNodeName());
               out.print("=\"");
               out.print(normalize(attr.getNodeValue(), canonical));
               out.print('"');
            }
            out.print('>');
            NodeList children = node.getChildNodes();
            if (children != null) {
               int len = children.getLength();
               for (int i = 0; i < len; i++) {
                  print(out, canonical, children.item(i));
               }
            }
            break;
         }

         //-------------------------------
         // Handle entity reference nodes.
         //-------------------------------

         case Node.ENTITY_REFERENCE_NODE: {
            if (canonical) {
               NodeList children = node.getChildNodes();
               if (children != null) {
                  int len = children.getLength();
                  for (int i = 0; i < len; i++) {
                     print(out, canonical, children.item(i));
                  }
               }
            }
            else {
               out.print('&');
               out.print(node.getNodeName());
               out.print(';');
            }
            break;
         }

         //------------
         // Print text.
         //------------

         case Node.TEXT_NODE: {
            out.print(normalize(node.getNodeValue(), canonical));
            break;
         }

         //-------------
         // Print CDATA.
         //-------------

         case Node.CDATA_SECTION_NODE: {
            if (canonical) {
               out.print(normalize(node.getNodeValue(), canonical));
            } else {
               out.print("<![CDATA[");
               out.print(node.getNodeValue());
               out.print("]]>");
            }
            break;
         }

         //------------------------------
         // Print processing instruction.
         //------------------------------

         case Node.PROCESSING_INSTRUCTION_NODE: {
            out.print("<?");
            out.print(node.getNodeName());
            String data = node.getNodeValue();
            if (data != null && data.length() > 0) {
               out.print(' ');
               out.print(data);
            }
            out.print("?>");
            break;
         }
      }

      //----------------------------
      // Print end tag if necessary.
      //----------------------------

      if (type == Node.ELEMENT_NODE) {
         out.print("</");
         out.print(node.getNodeName());
         out.print('>');
      }

   }


   //============================================================
   // Private method to Normalize the given string.
   //
   // This code was adapted from the sample code "DOMWriter.java"
   // included with XML4J.
   //============================================================

   private static String normalize(String s, boolean canonical) {
      StringBuffer str = new StringBuffer();

      int len = (s != null) ? s.length() : 0;
      for (int i = 0; i < len; i++) {
         char ch = s.charAt(i);
         switch (ch) {
            case '<': {
               str.append("&lt;");
               break;
            }
            case '>': {
               str.append("&gt;");
               break;
            }
            case '&': {
               str.append("&amp;");
               break;
            }
            case '"': {
               str.append("&quot;");
               break;
            }
            case '\r':
            case '\n': {
               if (canonical) {
                  str.append("&#");
                  str.append(Integer.toString(ch));
                  str.append(';');
                  break;
               }
               // else, default append char
            }
            default: {
               str.append(ch);
            }
         }
      }
      return str.toString();
    }


   //============================================================
   // Private method that returns a sorted list of attributes.
   //
   // This code was adapted from the sample code "DOMWriter.java"
   // included with XML4J.
   //============================================================

   private static Attr[] sortAttributes(NamedNodeMap attrs) {

      int len = (attrs != null) ? attrs.getLength() : 0;
      Attr array[] = new Attr[len];
      for (int i = 0; i < len; i++) {
          array[i] = (Attr)attrs.item(i);
      }
      for (int i = 0; i < len - 1; i++) {
         String name  = array[i].getNodeName();
         int    index = i;
         for (int j = i + 1; j < len; j++) {
            String curName = array[j].getNodeName();
            if (curName.compareTo(name) < 0) {
               name  = curName;
               index = j;
            }
         }
         if (index != i) {
            Attr temp    = array[i];
            array[i]     = array[index];
            array[index] = temp;
         }
      }
      return array;
   }

xml-dev: A list for W3C XML Developers. To post, mailto:xml-dev at ic.ac.uk
Archived as: http://www.lists.ic.ac.uk/hypermail/xml-dev/ and on CD-ROM/ISBN 981-02-3594-1
To (un)subscribe, mailto:majordomo at ic.ac.uk the following message;
(un)subscribe xml-dev
To subscribe to the digests, mailto:majordomo at ic.ac.uk the following message;
subscribe xml-dev-digest
List coordinator, Henry Rzepa (mailto:rzepa at ic.ac.uk)





More information about the Xml-dev mailing list