Project

General

Profile

1 87 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that transforms an XML text document
4
 *             into a another type using XSL
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones
8 349 jones
 *    Release: @release@
9 87 jones
 *
10 203 jones
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 669 jones
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 87 jones
 */
28
29
package edu.ucsb.nceas.metacat;
30
31
import java.io.*;
32
import java.net.URL;
33
import java.net.MalformedURLException;
34
import java.sql.*;
35
import java.util.Stack;
36
37 906 berkley
import javax.xml.transform.TransformerFactory;
38
import javax.xml.transform.Transformer;
39
import javax.xml.transform.stream.StreamSource;
40
import javax.xml.transform.stream.StreamResult;
41
import javax.xml.transform.TransformerException;
42
import javax.xml.transform.TransformerConfigurationException;
43
44
import org.apache.xerces.parsers.DOMParser;
45
import org.w3c.dom.Attr;
46
import org.w3c.dom.NamedNodeMap;
47
import org.w3c.dom.NodeList;
48
import org.w3c.dom.Document;
49
import org.w3c.dom.Node;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.DocumentType;
52
import org.xml.sax.SAXException;
53
import org.xml.sax.InputSource;
54
import org.apache.xerces.dom.DocumentTypeImpl;
55
import org.apache.xpath.XPathAPI;
56
import org.w3c.dom.NamedNodeMap;
57
58
/*
59 87 jones
import oracle.xml.parser.v2.XSLStylesheet;
60
import oracle.xml.parser.v2.XSLException;
61 832 jones
import oracle.xml.parser.v2.XMLParseException;
62 87 jones
import oracle.xml.parser.v2.XSLProcessor;
63
import oracle.xml.parser.v2.XMLDocument;
64
import oracle.xml.parser.v2.DOMParser;
65 906 berkley
*/
66 832 jones
import org.w3c.dom.Document;
67
import org.w3c.dom.Node;
68
import org.w3c.dom.Element;
69
import org.xml.sax.SAXException;
70 87 jones
71
/**
72
 * A Class that transforms XML documents utitlizing XSL style sheets
73
 */
74
public class DBTransform {
75
76
  private Connection	conn = null;
77 832 jones
  private MetaCatUtil   util = null;
78
  private String 	configDir = null;
79
  private String	defaultStyle = null;
80 87 jones
81
  /**
82
   * construct a DBTransform instance.
83
   *
84
   * Generally, one calls transformXMLDocument() after constructing the instance
85
   *
86
   * @param conn the database connection from which to lookup the public ids
87
   */
88
  public DBTransform( Connection conn )
89
                  throws IOException,
90
                         SQLException,
91
                         ClassNotFoundException
92
  {
93
    this.conn = conn;
94 832 jones
    util = new MetaCatUtil();
95
    configDir = util.getOption("config-dir");
96
    defaultStyle = util.getOption("default-style");
97 87 jones
  }
98
99
  /**
100
   * Transform an XML document using the stylesheet reference from the db
101
   *
102
   * @param doc the document to be transformed
103
   * @param sourcetype the document type of the source
104
   * @param targettype the target document type
105 832 jones
   * @param qformat the name of the style set to use
106
   * @param pw the PrintWriter to which output is printed
107 87 jones
   */
108 941 tao
  public void transformXMLDocument(String doc, String sourceType,
109
                String targetType, String qformat, PrintWriter pw) {
110 99 jones
111 87 jones
    // Look up the stylesheet for this type combination
112 941 tao
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
113 87 jones
114 941 tao
    if (xslSystemId != null) {
115 87 jones
      // Create a stylesheet from the system id that was found
116
      try {
117 906 berkley
        TransformerFactory tFactory = TransformerFactory.newInstance();
118
        Transformer transformer = tFactory.newTransformer(
119 941 tao
                                  new StreamSource(xslSystemId));
120
        transformer.setParameter("qformat", qformat);
121 906 berkley
        transformer.transform(new StreamSource(new StringReader(doc)),
122
                              new StreamResult(pw));
123 87 jones
      } catch (Exception e) {
124 941 tao
        pw.println(xslSystemId + "Error transforming document in " +
125 675 berkley
                   "DBTransform.transformXMLDocument: " +
126 87 jones
                   e.getMessage());
127 941 tao
128 87 jones
      }
129
    } else {
130
      // No stylesheet registered form this document type, so just return the
131
      // XML stream we were passed
132 100 jones
      pw.print(doc);
133 87 jones
    }
134
  }
135 906 berkley
136 941 tao
  /**
137
   * Transform an XML document to StringWriter using the stylesheet reference
138
   * from the db
139
   * @param doc the document to be transformed
140
   * @param sourceType the document type of the source
141
   * @param targetType the target document type
142
   * @param qFormat the name of the style set to use
143
   * @param pw the StringWriter to which output will be stored
144
   */
145
  public void transformXMLDocument(String doc, String sourceType,
146
                String targetType, String qFormat, StringWriter pw) {
147
148
    // Look up the stylesheet for this type combination
149
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
150
151
    if (xslSystemId != null) {
152
      // Create a stylesheet from the system id that was found
153
      try {
154
        TransformerFactory tFactory = TransformerFactory.newInstance();
155
        Transformer transformer = tFactory.newTransformer(
156
                                  new StreamSource(xslSystemId));
157
        transformer.setParameter("qFormat", qFormat);
158
        transformer.transform(new StreamSource(new StringReader(doc)),
159
                              new StreamResult(pw));
160
      } catch (Exception e) {
161
        util.debugMessage(xslSystemId + "Error transforming document in " +
162
                   "DBTransform.transformXMLDocument: " +
163
                   e.getMessage());
164
165
      }
166
    } else {
167
      // No stylesheet registered form this document type, so just return the
168
      // XML stream we were passed
169 950 tao
      pw.write(doc);
170 941 tao
    }
171
  }
172 906 berkley
173
  /**
174
   * gets the content of a tag in a given xml file with the given path
175
   * @param f the file to parse
176
   * @param path the path to get the content from
177
   */
178
  public static NodeList getPathContent(File f, String path)
179
  {
180
    if(f == null)
181
    {
182
      return null;
183
    }
184
185
    DOMParser parser = new DOMParser();
186
    InputSource in;
187
    FileInputStream fs;
188
189
    try
190
    {
191
      fs = new FileInputStream(f);
192
      in = new InputSource(fs);
193
    }
194
    catch(FileNotFoundException fnf)
195
    {
196
      fnf.printStackTrace();
197
      return null;
198
    }
199
200
    try
201
    {
202
      parser.parse(in);
203
      fs.close();
204
    }
205
    catch(Exception e1)
206
    {
207
      System.err.println("File: " + f.getPath() + " : parse threw: " +
208
                         e1.toString());
209
      return null;
210
    }
211
212
    Document doc = parser.getDocument();
213
214
    try
215
    {
216
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
217
      return docNodeList;
218
    }
219
    catch(Exception se)
220
    {
221
      System.err.println("file: " + f.getPath() + " : parse threw: " +
222
                         se.toString());
223
      return null;
224
    }
225
  }
226 87 jones
227
  /**
228
   * Lookup a stylesheet reference from the db catalog
229
   *
230 832 jones
   * @param qformat    the named style-set format
231
   * @param sourcetype the document type of the source
232
   * @param targettype the document type of the target
233
   */
234
  public String getStyleSystemId(String qformat, String sourcetype,
235
                String targettype) {
236
    String systemId = null;
237
238
    if ((qformat == null) || (qformat.equals("html"))) {
239
      qformat = defaultStyle;
240
    }
241
242
    // Load the style-set map for this qformat into a DOM
243
    try {
244 906 berkley
      boolean breakflag = false;
245 832 jones
      String filename = configDir + "/" + qformat + ".xml";
246
      util.debugMessage("Trying style-set file: " + filename);
247 906 berkley
      File f = new File(filename);
248
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
249
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
250
      Node nDefault = nlDefault.item(0);
251
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
252 832 jones
253 906 berkley
      for(int i=0; i<nlDoctype.getLength(); i++)
254
      { //look for the right sourcetype
255
        Node nDoctype = nlDoctype.item(i);
256
        NamedNodeMap atts = nDoctype.getAttributes();
257
        Node nAtt = atts.getNamedItem("publicid");
258
        String doctype = nAtt.getFirstChild().getNodeValue();
259
        if(doctype.equals(sourcetype))
260
        { //found the right sourcetype now we need to get the target type
261
          NodeList nlChildren = nDoctype.getChildNodes();
262
          for(int j=0; j<nlChildren.getLength(); j++)
263
          {
264
            Node nChild = nlChildren.item(j);
265
            String childName = nChild.getNodeName();
266
            if(childName.equals("target"))
267
            {
268
              NamedNodeMap childAtts = nChild.getAttributes();
269
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
270
              String target = nTargetPublicId.getFirstChild().getNodeValue();
271
              if(target.equals(targettype))
272
              { //we found the right target type
273
                NodeList nlTarget = nChild.getChildNodes();
274
                for(int k=0; k<nlTarget.getLength(); k++)
275
                {
276
                  Node nChildText = nlTarget.item(k);
277
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
278
                  { //get the text from the target node
279
                    systemId = nChildText.getNodeValue();
280
                    breakflag = true;
281
                    break;
282
                  }
283
                }
284 832 jones
              }
285
            }
286 906 berkley
287
            if(breakflag)
288
            {
289
              break;
290
            }
291 832 jones
          }
292
        }
293 906 berkley
294
        if(breakflag)
295
        {
296
          break;
297
        }
298 832 jones
      }
299
    }
300 906 berkley
    catch(Exception e)
301
    {
302
      System.out.println("Error parsing style-set file: " + e.getMessage());
303
      e.printStackTrace();
304
    }
305 832 jones
306
    // Return the system ID for this particular source document type
307
    return systemId;
308
  }
309
310
  /**
311
   * Lookup a stylesheet reference from the db catalog
312
   *
313 87 jones
   * @param objecttype the type of the object we want to retrieve
314
   * @param sourcetype the document type of the source
315
   * @param targettype the document type of the target
316
   */
317
  public String getSystemId(String objecttype, String sourcetype,
318
                String targettype) {
319
320
    // Look up the System ID of a particular object
321
    PreparedStatement pstmt;
322
    String the_system_id = null;
323
    try {
324
      pstmt =
325
        conn.prepareStatement("SELECT system_id " +
326 94 jones
                "FROM xml_catalog " +
327 764 bojilova
                "WHERE entry_type = ? " +
328
                "AND source_doctype = ? " +
329
                "AND target_doctype = ? ");
330 87 jones
      // Bind the values to the query
331 94 jones
      pstmt.setString(1, objecttype);
332
      pstmt.setString(2, sourcetype);
333
      pstmt.setString(3, targettype);
334 87 jones
      pstmt.execute();
335
      try {
336
        ResultSet rs = pstmt.getResultSet();
337
        try {
338
          boolean tableHasRows = rs.next();
339
          if (tableHasRows) {
340
            try {
341
              the_system_id = rs.getString(1);
342
            } catch (SQLException e) {
343 675 berkley
              System.out.println("Error with getString in " +
344
                                 "DBTransform.getSystemId: " + e.getMessage());
345
            }
346 87 jones
          } else {
347
            the_system_id = null;
348
          }
349
        } catch (SQLException e) {
350 675 berkley
          System.err.println("Error with next in DBTransform.getSystemId: " +
351
                              e.getMessage());
352 87 jones
          return ("Error with next: " + e.getMessage());
353
        }
354
      } catch (SQLException e) {
355 675 berkley
        System.err.println("Error with getrset in DBTransform.getSystemId: " +
356
                            e.getMessage());
357 87 jones
        return ("Error with getrset: " + e.getMessage());
358
      }
359
      pstmt.close();
360
    } catch (SQLException e) {
361 675 berkley
      System.err.println("Error getting id in DBTransform.getSystemId: " +
362
                          e.getMessage());
363
      return ("Error getting id in DBTransform.getSystemId:: " +
364
               e.getMessage());
365 87 jones
    }
366
    return the_system_id;
367
  }
368 99 jones
369
  /**
370
   * the main routine used to test the transform utility.
371
   *
372 184 jones
   * Usage: java DBTransform
373 99 jones
   */
374
  static public void main(String[] args) {
375
376 184 jones
     if (args.length > 0)
377 99 jones
     {
378
        System.err.println("Wrong number of arguments!!!");
379 184 jones
        System.err.println("USAGE: java DBTransform");
380 99 jones
        return;
381
     } else {
382
        try {
383
384
          // Open a connection to the database
385 184 jones
          MetaCatUtil   util = new MetaCatUtil();
386
          Connection dbconn = util.openDBConnection();
387 99 jones
388
          // Create a test document
389
          StringBuffer testdoc = new StringBuffer();
390
          testdoc.append("<?xml version=\"1.0\"?>");
391
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
392
          testdoc.append("<dataset_id>DS001</dataset_id>");
393
          testdoc.append("<title>My test doc</title></eml-dataset>");
394
395
          // Transform the document to the new doctype
396
          DBTransform dbt = new DBTransform(dbconn);
397
          dbt.transformXMLDocument(testdoc.toString(),
398
                                   "-//NCEAS//eml-dataset//EN",
399
                                   "-//W3C//HTML//EN",
400 832 jones
                                   "knb",
401 99 jones
                                   new PrintWriter(System.out));
402
403
        } catch (Exception e) {
404
          System.err.println("EXCEPTION HANDLING REQUIRED");
405
          System.err.println(e.getMessage());
406
          e.printStackTrace(System.err);
407
        }
408
     }
409
  }
410
411 184 jones
  private void dbg(int position) {
412 99 jones
    System.err.println("Debug flag: " + position);
413
  }
414
415 87 jones
}