You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-users@xmlgraphics.apache.org by Jen Liu <da...@yahoo.com> on 2002/07/17 20:42:57 UTC

SAX Parser � XML

I am trying to create XML containing data retrieved from the database but not write into the disk then pass it with my XSL-FO into FOP to generate PDF file.  The following is the code I have and please advise if the code looks all right and how can I view the content written in XML string and which variable (string) I should pass as the equivalence as an actual XML file?

Thanks.

My Code:

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.sql.*;
import java.io.*;


public class DatabaseFilter extends XMLFilterImpl {

  public static void main(String[] args) throws SQLException {    
     new DatabaseFilter();
  }

  private Connection connection;
  
  // The string passed to the constructor must be a JDBC URL that contains all necessary 
  // information for connecting to the database such as host, port, username, password, and database name. 
  // For example, jdbc:mysql://host:port]/dbname?user=username&password=pass
  // The driver should have been loaded before this method is called dddsa

  public DatabaseFilter() throws SQLException {

     // Load the Oracle JDBC Driver
     try{
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
     }  catch(Exception e){ 
        }
 
      String connURL = "jdbc:oracle:thin:@10.17.182.6:1521:IASWDEV1";
      String connUser = "data";
      String connPwd = "data";
      String selectQuery = "SELECT * FROM apps";
 
 connection = DriverManager.getConnection(connURL, connUser, connPwd);

 try {
    parse(selectQuery) ;
 }  catch(Exception e){
   }

  }

   public void parse(String selectQuery) throws SAXException, IOException {     
    try {

      Statement statement = connection.createStatement();
      ResultSet data = statement.executeQuery(selectQuery);

      ResultSetMetaData metadata = data.getMetaData();
      int numFields = metadata.getColumnCount();
      
      Attributes emptyAttributes = new AttributesImpl();
      startElement("", "table", "table", emptyAttributes);

     while (data.next()) {

        startElement("", "record", "record", emptyAttributes);

        for (int field = 1; field <= numFields; field++) {
          AttributesImpl fieldAtts = new AttributesImpl();         
          
          int type = metadata.getColumnType(field);
          String typeName = getSchemaType(type);

          fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi:type", "NMTOKEN", typeName);

          String name = metadata.getColumnName(field);
          fieldAtts.addAttribute("", "name", "name", "NMTOKEN", name);
          
          // Convert nulls to empty elements with xsi:nil="true"
          Object value = data.getObject(field);

          file://System.out.println("Column Value = " + data.getObject(field));      

          if (value == null) { // null value in database
            fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi:nil", "NMTOKEN", "true");
              startElement("", "field", "field", fieldAtts);
            endElement("", "field", "field");
          }

          else { // non-null value
            startElement("", "field", "field", fieldAtts);
            convertToXML(data, field, type);
            endElement("", "field", "field");
          }
        }
        endElement("", "record", "record"); 
      }
      endElement("", "table", "table");

      file://System.out.println(fieldAtts.toString());  
      System.out.println("jenny" + emptyAttributes.toString());      
       
      statement.close();      

    }
    catch (SQLException e) {  // convert exception type
      throw new SAXException(e); 
    }
    
  }

  // I want the XML document to store values in the standard W3C XML Schema Language forms. 
  // This requires certain conversions depending on the type of the data

  private void convertToXML(ResultSet data, int field, int type) throws SQLException, SAXException {

    switch (type) {
      case Types.BINARY: 

      case Types.VARBINARY: 

      case Types.LONGVARBINARY: 
        hexEncode(data.getBinaryStream(field));
        break;

      case Types.BLOB:
        Blob blob = data.getBlob(field);
        hexEncode(blob.getBinaryStream());
        break;

      // String types may contain C0 control characters that are not legal in XML. How should this be handled????
      case Types.CLOB: 
        Clob clob = data.getClob(field);
        Reader r = clob.getCharacterStream();
        char[] text = new char[1024];
        int numRead;

        try {
          while ((numRead = r.read(text, 0, 1024)) != -1) {
            characters(text, 0, numRead); 
          }
        }
        catch (IOException e) {
          throw new SAXException("Read from CLOB failed");          
        }
        break;

      case Types.ARRAY:
        Array array = data.getArray(field);
        writeArray(array);
        break;

      default: // All other types can be handled as strings
        Object o = data.getObject(field); 
        if (o == null) return;                
        String s = o.toString(); 
        char[] value = s.toCharArray();
        characters(value, 0, value.length);
    }     

  }
  
  private void hexEncode(InputStream in) 
   throws SQLException, SAXException {
    
    try {
      int octet;

      while ((octet = in.read()) != -1) {
        StringWriter out = new StringWriter(2);
        if (octet < 16) out.write('0');
        out.write(Integer.toHexString(octet));
        char[] text = out.toString().toCharArray();
        characters(text, 0, 2);
      }
    }
    catch (IOException e) {
      throw new SAXException(e);
    }
    
  }
  
  private void writeArray(Array array) 
   throws SQLException, SAXException {
    
    ResultSet data = array.getResultSet();
    int type = array.getBaseType();
    String typeName = getSchemaType(type);

    while (data.next()) {

      AttributesImpl fieldAtts = new AttributesImpl();

      fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi:type", "NMTOKEN", typeName);

      startElement("", "component", "component", fieldAtts);

      convertToXML(data, 2, type);

      endElement("", "component", "component");
    }
    
  }
  
  public static String getSchemaType(int type) {
   
    switch (type) {
      case Types.ARRAY:         return "array";
      case Types.BIGINT:        return "xsd:long";
      case Types.BINARY:        return "xsd:hexBinary";
      case Types.BIT:           return "xsd:boolean";
      case Types.BLOB:          return "xsd:hexBinary";
      case Types.CHAR:          return "xsd:string";
      case Types.CLOB:          return "xsd:string";
      case Types.DATE:          return "xsd:date";
      case Types.DECIMAL:       return "xsd:decimal";
      case Types.DOUBLE:        return "xsd:double";
      case Types.FLOAT:         return "xsd:decimal";
      case Types.INTEGER:       return "xsd:int";
      case Types.JAVA_OBJECT:   return "xsd:string";
      case Types.LONGVARBINARY: return "xsd:hexBinary";
      case Types.LONGVARCHAR:   return "xsd:string";
      case Types.NUMERIC:       return "xsd:decimal";
      case Types.REAL:          return "xsd:float";
      case Types.REF:           return "xsd:IDREF";
      case Types.SMALLINT:      return "xsd:short";
      case Types.STRUCT:        return "struct";
      case Types.TIME:          return "xsd:time";
      case Types.TIMESTAMP:     return "xsd:dateTime";
      case Types.TINYINT:       return "xsd:byte";
      case Types.VARBINARY:     return "xsd:hexBinary";
                                // most general type
      default:                  return "xsd:string"; 
    }
    
  }
  
  // Warn clients that this filter does not receive its events from another XML parser
  public void setParent(XMLReader parent) throws UnsupportedOperationException {
    throw new UnsupportedOperationException("A DatabaseFilter reads from an underlying SQL database;" + " not an underlying XML parser");
  }
  
}

 



---------------------------------
Do You Yahoo!?
Yahoo! Autos - Get free new car price quotes

Re: SAX Parser - XML

Posted by Denis Balazuc <De...@trader.com>.
As for FOP-ying your resulting XML (which should be some XSL:FO code), here's the code I use :

//FO->PDF
String foString = "?"//Your FO string;
Driver driver = new org.apache.fop.apps.Driver();
driver.setLogger(new ConsoleLogger());
driver.setRenderer(Driver.RENDER_PDF);
driver.setInputSource(new InputSource(new StringReader(foString )));
driver.setOutputStream(System.out);
driver.run();

//System.out contains the resulting PDF 


You can change the setInputSource() to take whatever you want in input (generally an URL or a Reader)
and the setOutputStream() to direct the output to a file, to a servlet outputstream, etc.

It might not be the more efficient way to do this, but it works fine for me.


>From what I read, you still need to transform your XML into a XSL:FO file before being able to render it as PDF.
Assuming you have a "transform.xsl" file that does such an XML->XSL:FO transformation, this is how you do this :

//Get the Templates object from the XSL file ("transform.xsl")
InputStream in = (new URL("transform.xsl")).openStream();
Source source = new StreamSource(in);
Templates templates =TransformerFactory.newInstance().newTemplates(source);

String xmlString = "?";//what you have extracted from the DB and parsed
StringReader reader = new StringReader(xmlString); //make it a stream usable for a Source object
StringWriter writer = new StringWriter(); //will be used to get the result of XLS transformation

templates.newTransformer().transform(new StreamSource(reader), new StreamResult(writer));
writer.close();

String foString = writer.toString(); //contains your XSL transformed XML now usable for FOP


Basically, you use the default TransformerFactory (see javax.xml.transform.*) for getting Templates instances that represent an XSL file.
Those Templates provides you with Transformer instances that are able to process a Source into a Result according to your XSL and the XML you use for the Source.
NB : you may want to cache the Templates instances but don't cache Transformer instances if you are in a multi-threaded environment.
You can safely cache TransformerFactory instances provided you don't want to dynamically change the implementation of it at runtime.


Hope this helps
Denis Balazuc

  ----- Original Message ----- 
  From: Jen Liu 
  To: fop-user@xml.apache.org 
  Sent: Wednesday, July 17, 2002 2:42 PM
  Subject: SAX Parser - XML


  I am trying to create XML containing data retrieved from the database but not write into the disk then pass it with my XSL-FO into FOP to generate PDF file.  The following is the code I have and please advise if the code looks all right and how can I view the content written in XML string and which variable (string) I should pass as the equivalence as an actual XML file?

  Thanks.

  My Code:

  import org.xml.sax.*;
  import org.xml.sax.helpers.*;
  import java.sql.*;
  import java.io.*;


  public class DatabaseFilter extends XMLFilterImpl {

    public static void main(String[] args) throws SQLException {    
       new DatabaseFilter();
    }

    private Connection connection;
    
    // The string passed to the constructor must be a JDBC URL that contains all necessary 
    // information for connecting to the database such as host, port, username, password, and database name. 
    // For example, jdbc:mysql://host:port]/dbname?user=username&password=pass
    // The driver should have been loaded before this method is called dddsa

    public DatabaseFilter() throws SQLException {

       // Load the Oracle JDBC Driver
       try{
          DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
       }  catch(Exception e){ 
          }
   
        String connURL = "jdbc:oracle:thin:@10.17.182.6:1521:IASWDEV1";
        String connUser = "data";
        String connPwd = "data";
        String selectQuery = "SELECT * FROM apps";
   
   connection = DriverManager.getConnection(connURL, connUser, connPwd);

   try {
      parse(selectQuery) ;
   }  catch(Exception e){
     }

    }

     public void parse(String selectQuery) throws SAXException, IOException {     
      try {

        Statement statement = connection.createStatement();
        ResultSet data = statement.executeQuery(selectQuery);

        ResultSetMetaData metadata = data.getMetaData();
        int numFields = metadata.getColumnCount();
        
        Attributes emptyAttributes = new AttributesImpl();
        startElement("", "table", "table", emptyAttributes);

       while (data.next()) {

          startElement("", "record", "record", emptyAttributes);

          for (int field = 1; field <= numFields; field++) {
            AttributesImpl fieldAtts = new AttributesImpl();         
            
            int type = metadata.getColumnType(field);
            String typeName = getSchemaType(type);

            fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi:type", "NMTOKEN", typeName);

            String name = metadata.getColumnName(field);
            fieldAtts.addAttribute("", "name", "name", "NMTOKEN", name);
            
            // Convert nulls to empty elements with xsi:nil="true"
            Object value = data.getObject(field);

            file://System.out.println("Column Value = " + data.getObject(field));      

            if (value == null) { // null value in database
              fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi:nil", "NMTOKEN", "true");
                startElement("", "field", "field", fieldAtts);
              endElement("", "field", "field");
            }

            else { // non-null value
              startElement("", "field", "field", fieldAtts);
              convertToXML(data, field, type);
              endElement("", "field", "field");
            }
          }
          endElement("", "record", "record"); 
        }
        endElement("", "table", "table");

        file://System.out.println(fieldAtts.toString());  
        System.out.println("jenny" + emptyAttributes.toString());      
         
        statement.close();      

      }
      catch (SQLException e) {  // convert exception type
        throw new SAXException(e); 
      }
      
    }

    // I want the XML document to store values in the standard W3C XML Schema Language forms. 
    // This requires certain conversions depending on the type of the data

    private void convertToXML(ResultSet data, int field, int type) throws SQLException, SAXException {

      switch (type) {
        case Types.BINARY: 

        case Types.VARBINARY: 

        case Types.LONGVARBINARY: 
          hexEncode(data.getBinaryStream(field));
          break;

        case Types.BLOB:
          Blob blob = data.getBlob(field);
          hexEncode(blob.getBinaryStream());
          break;

        // String types may contain C0 control characters that are not legal in XML. How should this be handled????
        case Types.CLOB: 
          Clob clob = data.getClob(field);
          Reader r = clob.getCharacterStream();
          char[] text = new char[1024];
          int numRead;

          try {
            while ((numRead = r.read(text, 0, 1024)) != -1) {
              characters(text, 0, numRead); 
            }
          }
          catch (IOException e) {
            throw new SAXException("Read from CLOB failed");          
          }
          break;

        case Types.ARRAY:
          Array array = data.getArray(field);
          writeArray(array);
          break;

        default: // All other types can be handled as strings
          Object o = data.getObject(field); 
          if (o == null) return;                
          String s = o.toString(); 
          char[] value = s.toCharArray();
          characters(value, 0, value.length);
      }     

    }
    
    private void hexEncode(InputStream in) 
     throws SQLException, SAXException {
      
      try {
        int octet;

        while ((octet = in.read()) != -1) {
          StringWriter out = new StringWriter(2);
          if (octet < 16) out.write('0');
          out.write(Integer.toHexString(octet));
          char[] text = out.toString().toCharArray();
          characters(text, 0, 2);
        }
      }
      catch (IOException e) {
        throw new SAXException(e);
      }
      
    }
    
    private void writeArray(Array array) 
     throws SQLException, SAXException {
      
      ResultSet data = array.getResultSet();
      int type = array.getBaseType();
      String typeName = getSchemaType(type);

      while (data.next()) {

        AttributesImpl fieldAtts = new AttributesImpl();

        fieldAtts.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi:type", "NMTOKEN", typeName);

        startElement("", "component", "component", fieldAtts);

        convertToXML(data, 2, type);

        endElement("", "component", "component");
      }
      
    }
    
    public static String getSchemaType(int type) {
     
      switch (type) {
        case Types.ARRAY:         return "array";
        case Types.BIGINT:        return "xsd:long";
        case Types.BINARY:        return "xsd:hexBinary";
        case Types.BIT:           return "xsd:boolean";
        case Types.BLOB:          return "xsd:hexBinary";
        case Types.CHAR:          return "xsd:string";
        case Types.CLOB:          return "xsd:string";
        case Types.DATE:          return "xsd:date";
        case Types.DECIMAL:       return "xsd:decimal";
        case Types.DOUBLE:        return "xsd:double";
        case Types.FLOAT:         return "xsd:decimal";
        case Types.INTEGER:       return "xsd:int";
        case Types.JAVA_OBJECT:   return "xsd:string";
        case Types.LONGVARBINARY: return "xsd:hexBinary";
        case Types.LONGVARCHAR:   return "xsd:string";
        case Types.NUMERIC:       return "xsd:decimal";
        case Types.REAL:          return "xsd:float";
        case Types.REF:           return "xsd:IDREF";
        case Types.SMALLINT:      return "xsd:short";
        case Types.STRUCT:        return "struct";
        case Types.TIME:          return "xsd:time";
        case Types.TIMESTAMP:     return "xsd:dateTime";
        case Types.TINYINT:       return "xsd:byte";
        case Types.VARBINARY:     return "xsd:hexBinary";
                                  // most general type
        default:                  return "xsd:string"; 
      }
      
    }
    
    // Warn clients that this filter does not receive its events from another XML parser
    public void setParent(XMLReader parent) throws UnsupportedOperationException {
      throw new UnsupportedOperationException("A DatabaseFilter reads from an underlying SQL database;" + " not an underlying XML parser");
    }
    
  }







------------------------------------------------------------------------------
  Do You Yahoo!?
  Yahoo! Autos - Get free new car price quotes