[jdom-interest] Document root element is missing.

David Parker dlparker at facstaff.wisc.edu
Tue Apr 1 08:26:23 PST 2003


Skipped content of type multipart/alternative-------------- next part --------------
import java.io.*;
import org.jdom.*;
import java.util.*;

/**
 *
 * @author dp8
 * @version  1.0.1
 * Created on Mar 31, 2003
 *
 * Navigating JDOM Trees
 * Once you?ve parsed a document and formed a Document object, you?ll probably want to search it
 * to select out those parts of it your program is interested in.
 * In JDOM, most navigation takes place through the methods of the Element class.
 * The complete children of each Element are available as a java.util.List returned by the getContent() method.
 * Just the child elements of each Element are available in a java.util.List returned by the getChildren() method.
 * (Yes, the terminology is a little confusing here. This is a case where JDOM is marching out of step
 * with the rest of the XML world.
 * <b>JDOM uses the word children to refer only to child elements.</b>)
 *
 * Because JDOM uses the Java Collections API to manage the tree, it is simultaneously too polymorphic
 * (everything?s an object and must be cast to the right type before you can use it)
 * and not polymorphic enough (there?s no useful generic interface or superclass for navigation
 * such as DOM?s Node class.)
 *
 * <b>Consequently, you?re going to find yourself doing numerous tests with instanceof and casting to the determined type.</b>
 * Furthermore, there?s no standard traversal API as there is in DOM to help you avoid reinventing the wheel every time
 * you need to walk a tree or iterate a document.
 *
 * There is a Filter interface that can simplify some of the polymorphism and casting issues a little,
 * but it still won?t let you walk more than one level down the tree at a time.
 *
 */

public class QtiReader {
  /*
   * String constants that are important nodes in the QTI xml file.
   */
  private static String QUESTESTINTEROP = "questestinterop";
  private static String ITEM            = "item";
  private static String PRESENTATION    = "presentation";
  private static String FLOW            = "flow";
  private static String RESPONSE_LID    = "response_lid";
  private static String MATERIAL        = "material";
  private static String MATTEXT         = "mattext";
  private static String RENDER_CHOICE   = "render_choice";
  private static String FLOW_LABEL      = "flow_label";
  private static String RESPONSE_LABEL  = "response_label";
  private static String FLOW_MAT        = "flow_mat";
  private static String RESPROCESSING   = "resprocessing";
  private static String OUTCOMES        = "outcomes";
  private static String DECVAR          = "decvar";
  private static String RESPCONDITION   = "respcondition";
  private static String CONDITIONVAR    = "conditionvar";
  private static String VAREQUAL        = "varequal";
  private static String SETVAR          = "setvar";
  private static String DISPLAYFEEDBACK = "displayfeedback";
  private static String ITEMFEEDBACK    = "itemfeedback";

  private    int request_count = 0;
  private    int response_count = 0;

  private    java.lang.String            input   = "C:\\src\\in-utf-8.xml";
  private    java.lang.String            output  = "C:\\src\\out-utf-8.html";
  private    org.jdom.Document           doc      = null;
  private    org.jdom.Element            root     = null;

  public     java.lang.StringBuffer      html = new java.lang.StringBuffer();

  /**
   *  This <code>QtiReader</code> constructor with no parameters and
   *  is called from main() and uses the hard coded input and output files.
   */
  public QtiReader() {

  }//constructor

  /**
   *  <code>QtiReader</code> constructor has two parameters;
   *  that are the pathname of the input and output files.
   *  It calls the  setters for each property.
   *  @param in  string with the input pathname
   *  @param out string with the output pathname
   */
  public QtiReader(String in, String out) {
  setInput(in);
  setOutput(out);
  }//constructor

  /**
   * <code>main</code>is implemented so that it can be tested as a standalone application.
   * I call the default constructor with no parameters.  The input and output are hard coded.
   * If you change them to the relative pathname space then make sure theyare in the same
   * directory as the class.
   * <ol>
   *  <li>Instanciate the QtiReader class.</li>
   *  <li>Instanciate the QtiReader class.</li>
   *  <li>Instanciate the QtiReader class.</li>
   *  <li>Instanciate the QtiReader class.</li>
   * </ol>
   * @param args
   */
  public static void main(String[] args) {
    String in = "";
    QtiReader qtireader = new QtiReader();

  qtireader.readUtf8Input();
  if (qtireader.root != null) {
    qtireader.whichChild(qtireader.root);
    qtireader.dumpIT();
    qtireader.writeUtf8Output();
  }
  }


  /**
   * <code>readUtf8Input</code> decodes the byte stream into a character stream
   * and returns a java.io.String.
   * <ol>
   * <li>Opens a connection to an actual file.</li>
   * <li>Obtains input bytes from a file in a file system.</li>
   * <li>Creates an InputStreamReader that users the named character set.</li>
   * <li>InputStreamReader is a bridge between the byte stream to character stream.</li>
   * <li>It reads bytes and decodes them into characters using the specified character set.</li>
   * <li>Create a buffering character input stream that uses the default buffer size.</li>
   * <li>Reads a single character this method will block until a character is available,
   *      an I/O error occurs, or the end of the stream is reached.</li>
   * </ol>
   * @exception JDOMException Indicates a well-formedness error
   * @exception UnsupportedEncodingException, if the character encoding is not supported.
   * @exception FileNotFoundException, if the fails to open a file with the given pathname.
   * @exception IOException, the general io exception handler.
   * @exception Exception, if a condition exists that the method could not handle.
   * @return    The reader to the QTI character stream as a java.io.String.
   */
  private void readUtf8Input() {
   org.jdom.input.SAXBuilder builder = new org.jdom.input.SAXBuilder();
   //org.jdom.input.SAXBuilder builder = new org.jdom.input.SAXBuilder("org.apache.xerces.parsers.SAXParser");

   try {
     // Opens a connection to an actual file.
     // Obtains input bytes from a file in a file system.
     java.io.FileInputStream fis = new java.io.FileInputStream(this.input);

     // Creates an InputStreamReader that users the named character set.
     // InputStreamReader is a bridge between the byte stream to character stream.
     // It reads bytes and decodes them into characters using the specified character set.
     java.io.InputStreamReader isr = new java.io.InputStreamReader(fis, "UTF8");

     // Create a buffering character input stream that uses the default buffer size.
     // Class for reading character streams.
     java.io.Reader reader = new java.io.BufferedReader(isr);
     System.out.println("past - this.reader");


     int ch;
     java.lang.StringBuffer buffer = new java.lang.StringBuffer();
     //System.out.println("\n\n\t*** " + reader.read() + " ***\n\n\n");

     while ((ch = reader.read()) > -1) {
          buffer.append((char)ch);
     }
     System.out.println("past - while loop, buffer length is " + buffer.length());
     System.out.println("Dumping " + input + "\n" + buffer.toString());

     this.doc    = builder.build(buffer.toString());
     System.out.println("past - this.doc");

     this.root   = this.doc.getRootElement();
     System.out.println("past - this.root");

     reader.close();

     // indicates a well-formedness error
   } catch (org.jdom.JDOMException jde) {
     System.out.println("\n\n\nJDOMException: " + input + " is not well-formed.\n");
     System.out.println(jde.toString());
     System.out.println(jde.getMessage());
     //jde.printStackTrace();

   } catch (java.io.UnsupportedEncodingException use) {
     use.printStackTrace();

   } catch (java.io.FileNotFoundException fnfe) {
     fnfe.printStackTrace();

   } catch (java.lang.Exception e) {
     e.printStackTrace();

   } finally {    }

  }


  /**
   *
   * @param c
   * @return
   */
  private String escape(char c) {

      StringBuffer b = new StringBuffer();
      for (int i = 0; i < 4; i++) {
          b.append(Integer.toHexString(c & 0x000F).toUpperCase());
          c >>>= 4;
      }
      b.append("u\\");
      return b.reverse().toString();
  }

  /**
   *
   * @param s
   */
  private void decode(String s) {
    char[] ch = s.toCharArray();
      for (int i = 0; i < ch.length; i++) {
          if(ch[i] < 128) {
              System.out.print(ch[i]);
          } else {
              System.out.print(this.escape(ch[i]));
          }
      }
    System.out.println();
  }



   /**
    * <code>writeUtf8Output</code> take a string that is the QTI xml text
    * that needs to be persisted tothe file system.
    * <ol>
    * <li>Creates an output file stream to write to the file with the specified name.</li>
    * <li>Creates an OutputStreamWriter that uses the named character set.</li>
    * <li>Take the stringbuffer were the HTML has been appened and send it to the writer().
    * </ol>
    *
    * @exception UnsupportedEncodingException, if the character encoding is not supported.
    * @exception FileNotFoundException, if the fails to open a file with the given pathname.
    * @exception IOException, the general io exception handler.
    * @exception Exception, if a condition exists that the method could not handle.
    */
   private void writeUtf8Output() {
   java.io.FileOutputStream fos = null;
   java.io.Writer out = null;

       try {
           // Creates an output file stream to write to the file with the specified name.
       fos = new FileOutputStream(output);

       // Creates an OutputStreamWriter that uses the named character set.
       out = new OutputStreamWriter(fos, "UTF8");

       // The OutputStreamWriter is a bridge from charater streams to byte streams.
       // The HTML character stream is written to the file system.
       out.write(this.html.toString());
       out.close();
       fos.close();

     } catch (java.io.UnsupportedEncodingException use) {
       use.printStackTrace();

     } catch (java.io.FileNotFoundException fnfe) {
       fnfe.printStackTrace();

       } catch (java.io.IOException ioe) {
           ioe.printStackTrace();

     } catch (java.lang.Exception e) {
       e.printStackTrace();

       } finally { }
   }


  /**
   *
   * @param current
   */
  public void whichChild(Element current) {
      String node = current.getName();
        String attribute = "";
        String text  = "";
        String title = "";

      if ( node.equals(QUESTESTINTEROP) ) {
        System.out.println(node);
          this.html.append("\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        this.html.append("\n<table xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");
          listChildren(current);
          this.html.append("\n</table>");
        return;

      } else if (node.equals(ITEM))     {
        System.out.println("\t"+node);
        title = current.getAttribute("title").getValue();
          listChildren(current);
          return;


      } else if (node.equals(PRESENTATION)) {
        //This will return the actual textual value of this Attribute.
        //This will include all text within the quotation marks.
        attribute = current.getAttribute("label").getValue();
        System.out.println("\t\t"+node+ "\t" +attribute);
        listChildren(current);
          return;

      } else if (node.equals(FLOW)) {
          System.out.println("\t\t\t"+node);
          listChildren(current);
          return;

      } else if (node.equals(RESPONSE_LID)) {
        request_count++;
        text = current.getChild(MATERIAL).getChild(MATTEXT).getText();
        this.decode(current.getChild(MATERIAL).getChild(MATTEXT).getText());
        System.out.println("\n\t\t\t\t"+node+ " count is " + request_count+ " : " + text);

        if (response_count!=0 && response_count!=0) {
        response_count=0;
            appendCloseTable();
        }

          appendQuestion(text);
          listChildren(current);
          return;

      } else if (node.equals(RENDER_CHOICE)) {

          System.out.println("\t\t\t\t"+node);
          listChildren(current);
        return;

      } else if (node.equals(FLOW_LABEL)) {
          System.out.println("\t\t\t\t"+node);
          listChildren(current);
        return;

      } else if (node.equals(RESPONSE_LABEL)) {
          System.out.println("\t\t\t\t"+node);
          listChildren(current);
        return;

      } else if (node.equals(FLOW_MAT)) {
        response_count++;
        text = current.getChild(MATERIAL).getChild(MATTEXT).getText();
        this.decode(current.getChild(MATERIAL).getChild(MATTEXT).getText());

          System.out.println("\t\t\t\t"+node+ " response count is " + response_count+ " : " + text);
          appendChoice(text);
        listChildren(current);
        return;

      } else if (node.equals(RESPROCESSING)) {
        appendCloseTable();
        return;

      } else {
        return;

      }
  }//whichChild()


  /**
   *
   * @param current
   */
  public void listChildren(Element current) {
    try {
      List children = current.getChildren();
      Iterator iterator = children.iterator();

      while (iterator.hasNext()) {
        Element child = (Element) iterator.next();
        whichChild(child);
      }
    } catch (java.util.NoSuchElementException nsee) {
      System.out.println("java.util.NoSuchElementException\n\t ");
      System.out.print("\n\t" +nsee.getMessage()+ "\n\t" + nsee.toString());
    } catch ( Exception e) {
      System.out.println("Exception:\n ");
      System.out.println("Exception:toString()\n\t " + e.toString());
    }
  }//listChildren()



//****
//****  HTML strings
//****
//****


  public void appendHead(Element current) {
    this.html.append("\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    this.html.append("\n<table xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");

    listChildren(current);

    this.html.append("\n</table>");
  }


  public void appendQuestion(String text) {
    this.html.append("\n  <table width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");
    this.html.append("\n    <tr>");
    this.html.append("\n      <td>");
    this.html.append("\n        <table width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");
    this.html.append("\n          <tr>");
    this.html.append("\n            <td width=\"1%\"> . </td>");
    this.html.append("\n            <td width=\"3%\"> . </td>");
    this.html.append("\n            <td width=\"96%\">" +text+ "</td>");
    this.html.append("\n          </tr>");
    this.html.append("\n        </table>");
    this.html.append("\n      </td>");
    this.html.append("\n    </tr>");
    this.html.append("\n    <tr>");
    this.html.append("\n      <td>");
    this.html.append("\n        <table width=\"100%\" border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");

  }

  public void appendOpenTable(Element current) {
    listChildren(current);
    this.html.append("\n      </table>");
    this.html.append("\n      </td>");
    this.html.append("\n    </tr>");
    //this.html.append("\n  </table>");
  }

  public void appendChoice(String text) {
    this.html.append("\n          <tr>");
    this.html.append("\n            <td width=\"1%\"> . </td>");
    this.html.append("\n            <td width=\"3%\"> . </td>");
    this.html.append("\n            <td width=\"4%\"> . </td>");
    this.html.append("\n            <td width=\"92%\">" +text+ "</td>");
    this.html.append("\n          </tr>");
  }

  public void appendCloseTable() {
    this.html.append("\n        </table>");
    this.html.append("\n      </td>");
    this.html.append("\n    </tr>");

  }

   public void dumpIT() {
     System.out.println("**************");
     System.out.println(this.html.toString());
     System.out.println("**************");
   }

   /**
  *
  * @param s is the the pathname of the input file.
  */
   public void setInput(String s) {
   this.input = s;
   }

   /**
  *
  * @param s is the the pathname of the output file.
  */
   public void setOutput(String s) {
   this.output = s;
   }

  /**
   *
   * @return the pathname of the input file.
   */
  public String getInput() {
    return this.input;
  }

  /**
   *
   * @return the pathname of the output file.
   */
  public String getOutput() {
    return this.output;
  }

}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: in-utf-8.xml
Type: application/xml
Size: 2163 bytes
Desc: not available
Url : http://jdom.org/pipermail/jdom-interest/attachments/20030401/2d1c1851/in-utf-8.rdf


More information about the jdom-interest mailing list