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 1929 brooke
 * '$Author$'
11
 * '$Date$'
12 203 jones
 * '$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 1688 tao
import java.util.Enumeration;
36 1664 tao
import java.util.Hashtable;
37 87 jones
import java.util.Stack;
38
39 906 berkley
import javax.xml.transform.TransformerFactory;
40
import javax.xml.transform.Transformer;
41
import javax.xml.transform.stream.StreamSource;
42
import javax.xml.transform.stream.StreamResult;
43
import javax.xml.transform.TransformerException;
44
import javax.xml.transform.TransformerConfigurationException;
45
46 2663 sgarg
import org.apache.log4j.Logger;
47 906 berkley
import org.apache.xerces.parsers.DOMParser;
48
import org.w3c.dom.Attr;
49
import org.w3c.dom.NamedNodeMap;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.Document;
52
import org.w3c.dom.Node;
53
import org.w3c.dom.NodeList;
54
import org.w3c.dom.DocumentType;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.InputSource;
57
import org.apache.xerces.dom.DocumentTypeImpl;
58
import org.apache.xpath.XPathAPI;
59
import org.w3c.dom.NamedNodeMap;
60
61
/*
62 87 jones
import oracle.xml.parser.v2.XSLStylesheet;
63
import oracle.xml.parser.v2.XSLException;
64 832 jones
import oracle.xml.parser.v2.XMLParseException;
65 87 jones
import oracle.xml.parser.v2.XSLProcessor;
66
import oracle.xml.parser.v2.XMLDocument;
67
import oracle.xml.parser.v2.DOMParser;
68 906 berkley
*/
69 832 jones
import org.w3c.dom.Document;
70
import org.w3c.dom.Node;
71
import org.w3c.dom.Element;
72
import org.xml.sax.SAXException;
73 87 jones
74 1716 berkley
/**
75 87 jones
 * A Class that transforms XML documents utitlizing XSL style sheets
76
 */
77
public class DBTransform {
78
79 1217 tao
  //private Connection	conn = null;
80 832 jones
  private MetaCatUtil   util = null;
81
  private String 	configDir = null;
82
  private String	defaultStyle = null;
83 2663 sgarg
  private Logger logMetacat = Logger.getLogger(DBTransform.class);
84
85 87 jones
  /**
86
   * construct a DBTransform instance.
87
   *
88
   * Generally, one calls transformXMLDocument() after constructing the instance
89
   *
90
   * @param conn the database connection from which to lookup the public ids
91
   */
92 1716 berkley
  public DBTransform()
93
                  throws IOException,
94
                         SQLException,
95 87 jones
                         ClassNotFoundException
96
  {
97 1217 tao
    //this.conn = conn;
98 832 jones
    util = new MetaCatUtil();
99
    configDir = util.getOption("config-dir");
100
    defaultStyle = util.getOption("default-style");
101 87 jones
  }
102 1716 berkley
103 87 jones
  /**
104 1716 berkley
   * @see transformXMLDocument(String doc, String sourceType,
105
   *            String targetType, String qformat, PrintWriter pw,
106
   *            String sessionid)
107
   */
108
  public void transformXMLDocument(String doc, String sourceType,
109 1717 berkley
                String targetType, String qformat, PrintWriter pw,
110
                Hashtable param)
111 1716 berkley
  {
112 1717 berkley
    transformXMLDocument(doc, sourceType, targetType, qformat, pw, param, null);
113 1716 berkley
  }
114
115 2088 tao
   /**
116
   * @see transformXMLDocument(String doc, String sourceType,
117
   *            String targetType, String qFormat, StringWriter pw
118
   *            String sessionid)
119
   */
120
  public void transformXMLDocument(String doc, String sourceType,
121
                String targetType, String qFormat, StringWriter pw)
122
  {
123
    transformXMLDocument(doc, sourceType, targetType, qFormat, pw, null);
124
  }
125
126
127 1716 berkley
  /**
128 87 jones
   * Transform an XML document using the stylesheet reference from the db
129
   *
130
   * @param doc the document to be transformed
131
   * @param sourcetype the document type of the source
132
   * @param targettype the target document type
133 832 jones
   * @param qformat the name of the style set to use
134
   * @param pw the PrintWriter to which output is printed
135 1664 tao
   * @param params some parameters for eml2 transformation
136 87 jones
   */
137 1716 berkley
  public void transformXMLDocument(String doc, String sourceType,
138
                                   String targetType, String qformat,
139
                                   PrintWriter pw, Hashtable param,
140
                                   String sessionid)
141 1664 tao
 {
142 1716 berkley
143 87 jones
    // Look up the stylesheet for this type combination
144 941 tao
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
145 2088 tao
    if (xslSystemId != null)
146
    {
147
      try
148
      {// Create a stylesheet from the system id that was found
149
        doc = removeDOCTYPE(doc);
150
        StringReader xml = new StringReader(doc);
151
        StreamResult result = new StreamResult(pw);
152
        doTransform(xml, result, xslSystemId, param, qformat, sessionid);
153 87 jones
154 2088 tao
      }
155
      catch (Exception e)
156
      {
157 941 tao
        pw.println(xslSystemId + "Error transforming document in " +
158 675 berkley
                   "DBTransform.transformXMLDocument: " +
159 87 jones
                   e.getMessage());
160 1716 berkley
161 87 jones
      }
162 2088 tao
    }
163
    else
164
    {
165 1716 berkley
      // No stylesheet registered form this document type, so just return the
166 87 jones
      // XML stream we were passed
167 100 jones
      pw.print(doc);
168 87 jones
    }
169
  }
170 1716 berkley
171 941 tao
  /**
172 1716 berkley
   * Transform an XML document to StringWriter using the stylesheet reference
173 941 tao
   * from the db
174
   * @param doc the document to be transformed
175
   * @param sourceType the document type of the source
176
   * @param targetType the target document type
177
   * @param qFormat the name of the style set to use
178
   * @param pw the StringWriter to which output will be stored
179
   */
180
  public void transformXMLDocument(String doc, String sourceType,
181 1716 berkley
                String targetType, String qFormat, StringWriter pw,
182 2088 tao
                String sessionid)
183
  {
184 941 tao
185
    // Look up the stylesheet for this type combination
186
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
187 2088 tao
    if (xslSystemId != null)
188
    {
189 941 tao
      // Create a stylesheet from the system id that was found
190 2088 tao
      try
191
      {
192 1903 tao
        doc = removeDOCTYPE(doc);
193 2088 tao
        StringReader xml = new StringReader(doc);
194
        StreamResult result = new StreamResult(pw);
195
        doTransform(xml, result, xslSystemId, null, qFormat, sessionid);
196
      }
197
      catch (Exception e)
198
      {
199 2663 sgarg
        logMetacat.error(xslSystemId + "Error transforming document in " +
200 941 tao
                   "DBTransform.transformXMLDocument: " +
201 2663 sgarg
                   e.getMessage());
202 1716 berkley
203 941 tao
      }
204 2088 tao
    }
205
    else
206
    {
207 1716 berkley
      // No stylesheet registered form this document type, so just return the
208 941 tao
      // XML stream we were passed
209 950 tao
      pw.write(doc);
210 941 tao
    }
211
  }
212 1716 berkley
213 906 berkley
  /**
214 2088 tao
   * Method to do transform for a string reader
215
   * @param doc the document to be transformed
216
   * @param sourcetype the document type of the source
217
   * @param targettype the target document type
218
   * @param qformat the name of the style set to use
219
   * @param pw the PrintWriter to which output is printed
220
   * @param params some parameters for eml2 transformation
221 1716 berkley
   */
222 2088 tao
   public void transformXMLDocument(StringReader docContent, String sourceType,
223
                                   String targetType, String qformat,
224
                                   PrintWriter pw, Hashtable param,
225
                                   String sessionid)
226
   {
227
     // Look up the stylesheet for this type combination
228
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
229
    if (xslSystemId != null)
230
    {
231
      try
232
      {// Create a stylesheet from the system id that was found
233
        StreamResult result = new StreamResult(pw);
234
        doTransform(docContent, result, xslSystemId, param, qformat, sessionid);
235
236
      }
237
      catch (Exception e)
238
      {
239
        pw.println(xslSystemId + "Error transforming document in " +
240
                   "DBTransform.transformXMLDocument: " +
241
                   e.getMessage());
242
243
      }
244
    }
245
    else
246
    {
247
      // No stylesheet registered form this document type, so just return the
248
      // XML stream we were passed
249
      pw.print(docContent);
250
    }
251
   }
252
253
  /*
254
   * Method to do transfer
255
   */
256
  private void doTransform(StringReader docContent, StreamResult resultOutput,
257
                           String xslSystemId, Hashtable param,
258
                           String qformat, String sessionid)
259
                          throws Exception
260 1716 berkley
  {
261 2088 tao
    if (xslSystemId != null)
262
    {
263
        TransformerFactory tFactory = TransformerFactory.newInstance();
264
        Transformer transformer = tFactory.newTransformer(
265
                                  new StreamSource(xslSystemId));
266
        transformer.setParameter("qformat", qformat);
267 2663 sgarg
        logMetacat.warn("qformat: "+qformat);
268 1716 berkley
269 2088 tao
        if(sessionid != null)
270
        {
271
          transformer.setParameter("sessid", sessionid);
272
        }
273
        // Set up parameter for transformation
274
        if ( param != null)
275
        {
276
          Enumeration en = param.keys();
277
          while (en.hasMoreElements())
278
          {
279
            String key =(String)en.nextElement();
280
            String value = ((String[])(param.get(key)))[0];
281 2668 sgarg
            logMetacat.info(key+" : "+value);
282 2088 tao
            transformer.setParameter(key, value);
283
          }
284
        }
285
        StreamSource xml = new StreamSource(docContent);
286
        transformer.transform(xml,resultOutput);
287
    }
288
  }//doTransform
289
290
291 1716 berkley
  /**
292 906 berkley
   * gets the content of a tag in a given xml file with the given path
293
   * @param f the file to parse
294
   * @param path the path to get the content from
295
   */
296 1716 berkley
  public static NodeList getPathContent(File f, String path)
297 906 berkley
  {
298
    if(f == null)
299
    {
300
      return null;
301
    }
302 1716 berkley
303 906 berkley
    DOMParser parser = new DOMParser();
304
    InputSource in;
305
    FileInputStream fs;
306 1716 berkley
307 906 berkley
    try
308 1716 berkley
    {
309 906 berkley
      fs = new FileInputStream(f);
310
      in = new InputSource(fs);
311
    }
312
    catch(FileNotFoundException fnf)
313
    {
314
      fnf.printStackTrace();
315
      return null;
316
    }
317 1716 berkley
318 906 berkley
    try
319
    {
320
      parser.parse(in);
321
      fs.close();
322
    }
323
    catch(Exception e1)
324
    {
325 1716 berkley
      System.err.println("File: " + f.getPath() + " : parse threw: " +
326 906 berkley
                         e1.toString());
327
      return null;
328
    }
329 1716 berkley
330 906 berkley
    Document doc = parser.getDocument();
331 1716 berkley
332 906 berkley
    try
333
    {
334
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
335
      return docNodeList;
336
    }
337
    catch(Exception se)
338
    {
339 1716 berkley
      System.err.println("file: " + f.getPath() + " : parse threw: " +
340 906 berkley
                         se.toString());
341
      return null;
342
    }
343
  }
344 87 jones
345
  /**
346
   * Lookup a stylesheet reference from the db catalog
347
   *
348 832 jones
   * @param qformat    the named style-set format
349
   * @param sourcetype the document type of the source
350
   * @param targettype the document type of the target
351
   */
352 1716 berkley
  public String getStyleSystemId(String qformat, String sourcetype,
353 832 jones
                String targettype) {
354
    String systemId = null;
355
356
    if ((qformat == null) || (qformat.equals("html"))) {
357
      qformat = defaultStyle;
358
    }
359
360
    // Load the style-set map for this qformat into a DOM
361
    try {
362 906 berkley
      boolean breakflag = false;
363 1929 brooke
      String filename = configDir + "/" + qformat + "/" + qformat + ".xml";
364 2663 sgarg
      logMetacat.warn("Trying style-set file: " + filename);
365 906 berkley
      File f = new File(filename);
366
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
367
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
368
      Node nDefault = nlDefault.item(0);
369
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
370 1716 berkley
371 906 berkley
      for(int i=0; i<nlDoctype.getLength(); i++)
372
      { //look for the right sourcetype
373
        Node nDoctype = nlDoctype.item(i);
374
        NamedNodeMap atts = nDoctype.getAttributes();
375
        Node nAtt = atts.getNamedItem("publicid");
376
        String doctype = nAtt.getFirstChild().getNodeValue();
377
        if(doctype.equals(sourcetype))
378
        { //found the right sourcetype now we need to get the target type
379
          NodeList nlChildren = nDoctype.getChildNodes();
380
          for(int j=0; j<nlChildren.getLength(); j++)
381
          {
382
            Node nChild = nlChildren.item(j);
383
            String childName = nChild.getNodeName();
384
            if(childName.equals("target"))
385
            {
386
              NamedNodeMap childAtts = nChild.getAttributes();
387
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
388
              String target = nTargetPublicId.getFirstChild().getNodeValue();
389
              if(target.equals(targettype))
390
              { //we found the right target type
391
                NodeList nlTarget = nChild.getChildNodes();
392
                for(int k=0; k<nlTarget.getLength(); k++)
393
                {
394
                  Node nChildText = nlTarget.item(k);
395
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
396
                  { //get the text from the target node
397
                    systemId = nChildText.getNodeValue();
398
                    breakflag = true;
399
                    break;
400
                  }
401
                }
402 832 jones
              }
403
            }
404 1716 berkley
405 906 berkley
            if(breakflag)
406
            {
407
              break;
408
            }
409 832 jones
          }
410
        }
411 1716 berkley
412 906 berkley
        if(breakflag)
413
        {
414
          break;
415
        }
416 832 jones
      }
417
    }
418 906 berkley
    catch(Exception e)
419
    {
420
      System.out.println("Error parsing style-set file: " + e.getMessage());
421
      e.printStackTrace();
422
    }
423 832 jones
424
    // Return the system ID for this particular source document type
425 2663 sgarg
    logMetacat.info("style system id is: "+systemId);
426 832 jones
    return systemId;
427
  }
428
429 1896 tao
 /* Method to modified the system id of xml input -- make sure it
430
    points to system id in xml_catalog table
431
  */
432 2088 tao
  private void modifiedXmlStreamSource(StreamSource xml, String publicId)
433 1896 tao
                                       throws Exception
434
  {
435
    // make sure the xml is not null
436
    if (xml == null || publicId == null)
437
    {
438
      return;
439 87 jones
    }
440 2663 sgarg
    logMetacat.info("public id of input stream is " +publicId);
441 1896 tao
    // Get system id from xml_catalog table
442
    String systemId = DBEntityResolver.getDTDSystemID(publicId);
443 2663 sgarg
    logMetacat.info("system id of input stream from xml_catalog"
444
                               +"table is " +systemId);
445 1896 tao
    //set system id to input stream
446
    xml.setSystemId(systemId);
447 87 jones
  }
448 2088 tao
449 1903 tao
  /*
450
   * removes the DOCTYPE element and its contents from a Sting
451 2088 tao
   * used to avoid problems with incorrect SystemIDs
452 1903 tao
   */
453 2088 tao
  private String removeDOCTYPE(String in) {
454 1903 tao
    String ret = "";
455
    int startpos = in.indexOf("<!DOCTYPE");
456
    if (startpos>-1) {
457 2088 tao
      int stoppos = in.indexOf(">", startpos + 8);
458 1903 tao
      ret = in.substring(0,startpos) + in.substring(stoppos+1,in.length());
459
    } else {
460
      return in;
461
    }
462 2088 tao
    return ret;
463 1903 tao
  }
464 99 jones
465
  /**
466
   * the main routine used to test the transform utility.
467
   *
468 184 jones
   * Usage: java DBTransform
469 99 jones
   */
470
  static public void main(String[] args) {
471 1716 berkley
472 184 jones
     if (args.length > 0)
473 99 jones
     {
474
        System.err.println("Wrong number of arguments!!!");
475 184 jones
        System.err.println("USAGE: java DBTransform");
476 99 jones
        return;
477
     } else {
478
        try {
479 1716 berkley
480 99 jones
          // Open a connection to the database
481 1217 tao
          /*MetaCatUtil   util = new MetaCatUtil();
482
          Connection dbconn = util.openDBConnection();*/
483 99 jones
484
          // Create a test document
485
          StringBuffer testdoc = new StringBuffer();
486
          testdoc.append("<?xml version=\"1.0\"?>");
487
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
488
          testdoc.append("<dataset_id>DS001</dataset_id>");
489
          testdoc.append("<title>My test doc</title></eml-dataset>");
490
491
          // Transform the document to the new doctype
492 1217 tao
          DBTransform dbt = new DBTransform();
493 1716 berkley
          dbt.transformXMLDocument(testdoc.toString(),
494
                                   "-//NCEAS//eml-dataset//EN",
495
                                   "-//W3C//HTML//EN",
496 832 jones
                                   "knb",
497 1664 tao
                                   new PrintWriter(System.out), null);
498 99 jones
499
        } catch (Exception e) {
500
          System.err.println("EXCEPTION HANDLING REQUIRED");
501
          System.err.println(e.getMessage());
502
          e.printStackTrace(System.err);
503
        }
504
     }
505
  }
506 1716 berkley
507 184 jones
  private void dbg(int position) {
508 99 jones
    System.err.println("Debug flag: " + position);
509
  }
510
511 87 jones
}