KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > portal > common > util > XML


1 /*****************************************
2  * *
3  * JBoss Portal: The OpenSource Portal *
4  * *
5  * Distributable under LGPL license. *
6  * See terms of license at gnu.org. *
7  * *
8  *****************************************/

9
10 package org.jboss.portal.common.util;
11
12 import org.apache.xpath.CachedXPathAPI;
13 import org.w3c.dom.Attr JavaDoc;
14 import org.w3c.dom.DOMException JavaDoc;
15 import org.w3c.dom.Document JavaDoc;
16 import org.w3c.dom.Element JavaDoc;
17 import org.w3c.dom.NamedNodeMap JavaDoc;
18 import org.w3c.dom.Node JavaDoc;
19 import org.w3c.dom.NodeList JavaDoc;
20 import org.w3c.dom.Text JavaDoc;
21 import org.xml.sax.EntityResolver JavaDoc;
22 import org.xml.sax.ErrorHandler JavaDoc;
23 import org.xml.sax.InputSource JavaDoc;
24 import org.xml.sax.SAXException JavaDoc;
25 import org.xml.sax.helpers.DefaultHandler JavaDoc;
26
27 import javax.xml.parsers.DocumentBuilder JavaDoc;
28 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
29 import javax.xml.parsers.ParserConfigurationException JavaDoc;
30 import javax.xml.parsers.SAXParser JavaDoc;
31 import javax.xml.parsers.SAXParserFactory JavaDoc;
32 import javax.xml.transform.OutputKeys JavaDoc;
33 import javax.xml.transform.Result JavaDoc;
34 import javax.xml.transform.Source JavaDoc;
35 import javax.xml.transform.Templates JavaDoc;
36 import javax.xml.transform.Transformer JavaDoc;
37 import javax.xml.transform.TransformerConfigurationException JavaDoc;
38 import javax.xml.transform.TransformerException JavaDoc;
39 import javax.xml.transform.TransformerFactory JavaDoc;
40 import javax.xml.transform.dom.DOMSource JavaDoc;
41 import javax.xml.transform.stream.StreamResult JavaDoc;
42 import javax.xml.transform.stream.StreamSource JavaDoc;
43 import java.io.ByteArrayInputStream JavaDoc;
44 import java.io.ByteArrayOutputStream JavaDoc;
45 import java.io.FileNotFoundException JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.io.InputStream JavaDoc;
48 import java.io.InputStreamReader JavaDoc;
49 import java.io.OutputStream JavaDoc;
50 import java.io.Reader JavaDoc;
51 import java.io.StringReader JavaDoc;
52 import java.io.StringWriter JavaDoc;
53 import java.io.Writer JavaDoc;
54 import java.net.URL JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.Properties JavaDoc;
57 import java.util.List JavaDoc;
58
59 /**
60  * Utilities for dealing with XML.
61  *
62  * @author <a HREF="mailto:mholzner@novell.com">Martin Holzner</a>
63  * @author <a HREF="mailto:julien@jboss.org">Julien Viet</a>
64  * @version $Revision: 1.8 $
65  */

66 public class XML
67 {
68
69    /**
70     * Namespace URI for XML lang.
71     */

72    public static final String JavaDoc XML_LANG_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
73
74    /**
75     * Document builder factory.
76     */

77    private static final DocumentBuilderFactory JavaDoc buildFactory = DocumentBuilderFactory.newInstance();
78
79    /**
80     * Transformer factory.
81     */

82    private static final TransformerFactory JavaDoc transformerFactory = TransformerFactory.newInstance();
83
84    /**
85     * Default output format which is : no xml declaration, no document type, indent.
86     */

87    private static Properties JavaDoc DEFAULT_FORMAT = new Properties JavaDoc();
88
89    /**
90     *
91     */

92    public static final String JavaDoc PARAM_YES = "yes";
93    /**
94     *
95     */

96    public static final String JavaDoc PARAM_NO = "no";
97    /**
98     *
99     */

100    public static final String JavaDoc ATTRIB_OMIT_XML_DECLARATION = "omit-xml-declaration";
101    /**
102     *
103     */

104    public static final String JavaDoc ATTRIB_CDATA_SECTION_ELEMENTS = "cdata-section-elements";
105    /**
106     *
107     */

108    public static final String JavaDoc ATTRIB_METHOD = "method";
109    /**
110     *
111     */

112    public static final String JavaDoc ATTRIB_INDENT = "indent";
113    /**
114     *
115     */

116    public static final String JavaDoc ATTRIB_HREF = "href";
117    /**
118     *
119     */

120    public static final String JavaDoc DIRECTIVE_IMPORT = "xsl:import";
121    /**
122     *
123     */

124    public static final String JavaDoc DIRECTIVE_INCLUDE = "xsl:include";
125    /**
126     *
127     */

128    public static final boolean DEFAULT_NAMESPACE_AWARE = true;
129    /**
130     *
131     */

132    public static final boolean DEFAULT_VALIDATION = false;
133
134    // cache for the SAX Parser factories
135
private static final SAXParserFactory JavaDoc[][] SAXPARSERFACTORIES = new SAXParserFactory JavaDoc[2][2];
136    private static TransformerFactory JavaDoc g_transformerFactory = null;
137    // ++TODO: replace these resource bundle accessors (!?)
138
private static final String JavaDoc ERR_NO_NULL_ARGS_ALLOWED = "1";
139    private static final String JavaDoc ERR_NO_NULL_DOC_AND_NODE_ALLOWED = "2";
140    private static final String JavaDoc ERR_NO_NULL_PARENT_AND_NODE_ALLOWED = "3";
141    private static final String JavaDoc ERR_NO_NULL_DOC_OR_PARENT_AND_NODE_ALLOWED = "4";
142    private static final String JavaDoc ERR_NO_NULL_PARENT_NODE_ALLOWED = "5";
143    private static final String JavaDoc ERR_NO_NULL_NODE_AND_ATTNAME_ALLOWED = "6";
144    private static final String JavaDoc ERR_NO_NULL_DOC_AND_ATTNAME_ALLOWED = "7";
145    private static final String JavaDoc ERR_NO_NULL_PARENT_AND_CONTENT_ALLOWED = "8";
146    private static final String JavaDoc ERR_NO_NULL_SIBLING_AND_NODE_ALLOWED = "9";
147    private static final String JavaDoc ERR_NO_NULL_DOC_AND_DIRECTIVENAME_ALLOWED = "10";
148    private static final String JavaDoc ERR_IS_NOT_A_STYLESHEET = "11";
149    private static final String JavaDoc ERR_NO_NULL_INPUTSOURCE_ALLOWED = "12";
150    private static final String JavaDoc MSG_FOUND_BY_PARENT = "13";
151    private static final String JavaDoc MSG_URI_NEEDS_RESOLUTION = "14";
152    private static final String JavaDoc MSG_RELATIVE_URI = "15";
153    private static final String JavaDoc MSG_NOT_RESOLVED = "16";
154    private static final String JavaDoc ERR_NO_RESOLVE = "17";
155    private static final String JavaDoc ERR_WRONG_NODETYPE = "18";
156    private static final String JavaDoc ERR_SRC_AND_DEST_DOC_EQUAL = "19";
157
158    static
159    {
160       DEFAULT_FORMAT.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
161       DEFAULT_FORMAT.setProperty(OutputKeys.INDENT, "yes");
162       DEFAULT_FORMAT.setProperty(OutputKeys.METHOD, "xml");
163       DEFAULT_FORMAT.setProperty(OutputKeys.ENCODING, "UTF-8");
164    }
165
166    // cache for the Document builders that we use globally
167
private static DocumentBuilderFactory JavaDoc[][] docBuilderFactories = new DocumentBuilderFactory JavaDoc[2][2];
168    static
169    {
170       DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
171       factory.setValidating(false);
172       factory.setNamespaceAware(false);
173
174       docBuilderFactories[0][0] = factory;
175
176       factory = DocumentBuilderFactory.newInstance();
177       factory.setValidating(false);
178       factory.setNamespaceAware(true);
179
180       docBuilderFactories[0][1] = factory;
181
182       factory = DocumentBuilderFactory.newInstance();
183       factory.setValidating(true);
184       factory.setNamespaceAware(false);
185
186       docBuilderFactories[1][0] = factory;
187
188       factory = DocumentBuilderFactory.newInstance();
189       factory.setValidating(true);
190       factory.setNamespaceAware(true);
191
192       docBuilderFactories[1][1] = factory;
193    }
194
195    // per thread cache for the Document builders
196
private static ThreadLocal JavaDoc documentBuilders = new ThreadLocal JavaDoc()
197    {
198       protected synchronized Object JavaDoc initialValue()
199       {
200          return new DocumentBuilder JavaDoc[2][2];
201       }
202    };
203
204    /**
205     * prevent instantiation
206     */

207    private XML()
208    {
209    }
210
211    /**
212     * Return the builder factory.
213     */

214    public static DocumentBuilderFactory JavaDoc getDocumentBuilderFactory()
215    {
216       return buildFactory;
217    }
218
219    /**
220     * Converts an element to a String representation.
221     */

222    public static final String JavaDoc toString(Element JavaDoc element, Properties JavaDoc properties) throws ParserConfigurationException JavaDoc, TransformerException JavaDoc
223    {
224       Document JavaDoc doc = buildFactory.newDocumentBuilder().newDocument();
225       element = (Element JavaDoc)doc.importNode(element, true);
226       doc.appendChild(element);
227       return toString(doc, properties);
228    }
229
230    /**
231     * @see #toString(Document)
232     */

233    public static final String JavaDoc toString(Element JavaDoc element) throws ParserConfigurationException JavaDoc, TransformerException JavaDoc
234    {
235       return toString(element, DEFAULT_FORMAT);
236    }
237
238    /**
239     * Serialize the document with the default format :
240     * - No XML declaration
241     * - Indented
242     * - Encoding is UTF-8
243     *
244     * @see #toString(Document,Properties)
245     */

246    public static final String JavaDoc toString(Document JavaDoc doc) throws TransformerException JavaDoc
247    {
248       return toString(doc, DEFAULT_FORMAT);
249    }
250
251    /**
252     * Converts an document to a String representation.
253     */

254    public static String JavaDoc toString(Document JavaDoc doc, Properties JavaDoc format) throws TransformerException JavaDoc
255    {
256       Transformer JavaDoc transformer = transformerFactory.newTransformer();
257       transformer.setOutputProperties(format);
258       StringWriter JavaDoc writer = new StringWriter JavaDoc();
259       Source JavaDoc source = new DOMSource JavaDoc(doc);
260       Result JavaDoc result = new StreamResult JavaDoc(writer);
261       transformer.transform(source, result);
262       return writer.toString();
263    }
264
265    /**
266     * Parse a string into a document.
267     */

268    public static Document JavaDoc toDocument(String JavaDoc text) throws ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
269    {
270       DocumentBuilder JavaDoc builder = buildFactory.newDocumentBuilder();
271       StringReader JavaDoc reader = new StringReader JavaDoc(text);
272       InputSource JavaDoc source = new InputSource JavaDoc();
273       source.setCharacterStream(reader);
274       Document JavaDoc doc = builder.parse(source);
275       return doc;
276    }
277
278    /**
279     * Parse a string into an element.
280     */

281    public static Element JavaDoc toElement(String JavaDoc text) throws ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
282    {
283       Document JavaDoc doc = toDocument(text);
284       return doc.getDocumentElement();
285    }
286
287    /**
288     * Perform trimming by default
289     *
290     * @see #asString(org.w3c.dom.Element, boolean)
291     * @param element
292     * @return
293     * @throws IllegalArgumentException
294     */

295    public static String JavaDoc asString(Element JavaDoc element) throws IllegalArgumentException JavaDoc
296    {
297       return asString(element, true);
298    }
299
300    /**
301     * Get the element's content as a string.
302     *
303     * @param element the container
304     * @trim true if text should be trimmed before returning result
305     * @throws IllegalArgumentException if the element content is mixed or null
306     */

307    public static String JavaDoc asString(Element JavaDoc element, boolean trim) throws IllegalArgumentException JavaDoc
308    {
309       if (element == null)
310       {
311          throw new IllegalArgumentException JavaDoc("No null element allowed");
312       }
313
314       //
315
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
316       NodeList JavaDoc children = element.getChildNodes();
317       for (int i = 0;i < children.getLength();i++)
318       {
319          Node JavaDoc child = children.item(i);
320          switch (child.getNodeType())
321          {
322          case Node.CDATA_SECTION_NODE:
323          case Node.TEXT_NODE:
324             buffer.append(((Text JavaDoc)child).getData());
325             break;
326          case Node.ELEMENT_NODE:
327             throw new IllegalArgumentException JavaDoc("Mixed content now allowed");
328          default:
329             break;
330          }
331       }
332       String JavaDoc result = buffer.toString();
333       if (trim)
334       {
335          result.trim();
336       }
337       return result;
338    }
339
340    /**
341     * Return the optional unique child of an element.
342     *
343     * @param element the parent element
344     * @param strict true if the element must be present
345     * @return the child element or null if it does not exist and strict is false
346     * @throws IllegalArgumentException if an argument is null
347     * @throws NoSuchElementException if strict is true and the element is not present
348     * @throws TooManyElementException if more than one element is found
349     */

350    public static Element JavaDoc getUniqueChild(Element JavaDoc element, boolean strict) throws IllegalArgumentException JavaDoc,
351       NoSuchElementException, TooManyElementException
352    {
353       if (element == null)
354       {
355          throw new IllegalArgumentException JavaDoc("No element specified");
356       }
357       Element JavaDoc childElt = null;
358       NodeList JavaDoc list = element.getChildNodes();
359       for (int i = 0; i < list.getLength(); i++)
360       {
361          Node JavaDoc childNode = list.item(i);
362          if (childNode instanceof Element JavaDoc)
363          {
364             if (childElt == null)
365             {
366                childElt = (Element JavaDoc)childNode;
367             }
368             else
369             {
370                throw new TooManyElementException("More than one child element for element " + element.getNodeName());
371             }
372          }
373       }
374       if (strict && childElt == null)
375       {
376          throw new NoSuchElementException("No child element for element " + element.getNodeName());
377       }
378       return childElt;
379    }
380
381    /**
382     * Return an optional child of an element with the specified name.
383     *
384     * @param element the parent element
385     * @param name the child name
386     * @param strict if the child must be present
387     * @return the child element or null if it does not exist and strict is set to false
388     * @throws IllegalArgumentException if an argument is null
389     * @throws NoSuchElementException if strict is true and the element is not present
390     * @throws TooManyElementException if more than one element is found
391     */

392    public static Element JavaDoc getUniqueChild(Element JavaDoc element, String JavaDoc name, boolean strict) throws IllegalArgumentException JavaDoc,
393       NoSuchElementException, TooManyElementException
394    {
395       List JavaDoc list = getChildren(element, name);
396       switch (list.size())
397       {
398       case 0:
399          if (strict)
400          {
401             throw new NoSuchElementException("Missing child " + name + " of element " + element.getNodeName());
402          }
403          else
404          {
405             return null;
406          }
407       case 1:
408          return (Element JavaDoc)list.get(0);
409       default:
410          throw new TooManyElementException("Too many children for element " + element.getNodeName());
411       }
412    }
413
414    /**
415     * Return all the children of the given element having the specified name. The collection object can be modified.
416     *
417     * @param element the parent element
418     * @param name the child names
419     * @return a list of elements
420     * @throws IllegalArgumentException if the element is null or the name is null
421     */

422    public static List JavaDoc getChildren(Element JavaDoc element, String JavaDoc name) throws IllegalArgumentException JavaDoc
423    {
424       if (element == null)
425       {
426          throw new IllegalArgumentException JavaDoc("No element found");
427       }
428       if (name == null)
429       {
430          throw new IllegalArgumentException JavaDoc("No name specified");
431       }
432       ArrayList JavaDoc result = new ArrayList JavaDoc();
433       NodeList JavaDoc list = element.getChildNodes();
434       for (int i = 0; i < list.getLength(); i++)
435       {
436          Node JavaDoc node = list.item(i);
437          if (node.getNodeType() == Node.ELEMENT_NODE)
438          {
439             Element JavaDoc childElt = (Element JavaDoc)node;
440             if (childElt.getTagName().equals(name))
441             {
442                result.add(childElt);
443             }
444          }
445       }
446       return result;
447    }
448
449    /**
450     * get a javax.xml.parsers.DocumentBuilder from the javax.xml.parsers.DocumentBuilderFactory validation turned off
451     * and name space awareness turned on if you need a DocumentBuilder with different features, use the
452     * getBuilder(boolean validation, boolean nameSpaceAware) method
453     *
454     * @return DocumentBuilder
455     * @throws javax.xml.parsers.ParserConfigurationException
456     * if the parser is not configured
457     * @see #getBuilder(boolean, boolean)
458     */

459    public static DocumentBuilder JavaDoc getBuilder() throws ParserConfigurationException JavaDoc
460    {
461       // our default is: validation no false, namespace yes true
462
return getBuilder(DEFAULT_VALIDATION, DEFAULT_NAMESPACE_AWARE);
463    }
464
465    /**
466     * get a javax.xml.parsers.DocumentBuilder from the javax.xml.parsers.DocumentBuilderFactory
467     * Using this method will cache the DocumentBuilder in thread local storage after the fist hit
468     *
469     * @param validation true if validation should be turned on, otherwise use false
470     * @param nameSpaceAware true if name space awareness should be turned on, otherwise use false
471     * @return a DocumentBuilder to create Documents
472     * @throws javax.xml.parsers.ParserConfigurationException
473     * if the underlying parser does
474     */

475    public static DocumentBuilder JavaDoc getBuilder(final boolean validation, final boolean nameSpaceAware)
476       throws ParserConfigurationException JavaDoc
477    {
478       // transform the booleans to int indexes
479
int validationIndex = validation ? 1 : 0;
480       int namespaceIndex = nameSpaceAware ? 1 : 0;
481       // keep doc builder in thread local storage (doesn't need to be synchronized)
482
DocumentBuilder JavaDoc[][] docBuilder = (DocumentBuilder JavaDoc[][])documentBuilders.get();
483       // if this combo is not yet in cache, then cache it now
484
if (docBuilder[validationIndex][namespaceIndex] == null)
485       {
486          docBuilder[validationIndex][namespaceIndex] = docBuilderFactories[validationIndex][namespaceIndex].newDocumentBuilder();
487       }
488       return docBuilder[validationIndex][namespaceIndex];
489    }
490
491    /**
492     * create a new org.w3c.dom.Document with validation turned off and name space awareness turned on
493     *
494     * @return the created org.w3c.dom.Document
495     * @throws javax.xml.parsers.ParserConfigurationException
496     * if the underlying parser does
497     */

498    public static Document JavaDoc createDocument() throws ParserConfigurationException JavaDoc
499    {
500       // create a new document
501
// It was request that this simple way of creating a document not throw any exception
502
// since it should always create one - this prevents the caller from having to catch
503

504       return getBuilder().newDocument();
505    }
506
507    /**
508     * Creates a Document from a String representing a valid XML document (no validation, but name space aware)
509     *
510     * @param strDoc the string representing the xml
511     * @return the created Document
512     * @throws org.w3c.dom.DOMException if the provided string does not represent a valid xml document
513     * @throws java.io.IOException on read problems
514     * @throws org.xml.sax.SAXException on parse problems
515     * @throws javax.xml.parsers.ParserConfigurationException
516     * if the underlying parser does
517     * @throws IllegalArgumentException if the passed string is null
518     */

519    public static Document JavaDoc createDocument(final String JavaDoc strDoc) throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc,
520       ParserConfigurationException JavaDoc
521    {
522
523       if (strDoc == null)
524       {
525          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
526       }
527
528       final InputSource JavaDoc inputSrc = new InputSource JavaDoc(new StringReader JavaDoc(strDoc));
529
530       return parseInputSource(inputSrc, DEFAULT_VALIDATION, DEFAULT_NAMESPACE_AWARE, null, null);
531    }
532
533    /**
534     * create a Document from a String representation (with name space awareness on and validation off)
535     *
536     * @param stream the InputStream that represents the XML Content
537     * @return a Document representing the same content
538     * @throws org.w3c.dom.DOMException if the InputSource does not represent a valid XML document
539     * @throws java.io.IOException on read problems
540     * @throws org.xml.sax.SAXException on parse problems
541     * @throws javax.xml.parsers.ParserConfigurationException
542     * if the underlying parser does
543     * @throws IllegalArgumentException if the provided InputSource is null
544     */

545    public static Document JavaDoc createDocument(final InputStream JavaDoc stream) throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc,
546       ParserConfigurationException JavaDoc
547    {
548
549       if (stream == null)
550       {
551          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
552       }
553
554       return parseInputSource(new InputSource JavaDoc(stream), DEFAULT_VALIDATION, DEFAULT_NAMESPACE_AWARE, null, null);
555    }
556
557    /**
558     * create a Document from a byte[]
559     *
560     * @param bytes the bytes that represents the XML Content
561     * @return a Document representing the same content
562     * @throws org.w3c.dom.DOMException if the InputSource does not represent a valid XML document
563     * @throws java.io.IOException on read problems
564     * @throws org.xml.sax.SAXException on parse problems
565     * @throws javax.xml.parsers.ParserConfigurationException
566     * if the underlying parser does
567     * @throws IllegalArgumentException if the provided InputSource is null
568     */

569    public static Document JavaDoc createDocument(final byte[] bytes) throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc,
570       ParserConfigurationException JavaDoc
571    {
572
573       if (bytes == null)
574       {
575          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
576       }
577       final java.io.ByteArrayInputStream JavaDoc bis = new java.io.ByteArrayInputStream JavaDoc(bytes);
578       return createDocument(bis);
579    }
580
581    /**
582     * create a Document from a stream representation of the XML content use the requested char-set encoding, validation
583     * and name space awareness
584     *
585     * @param stream the stream (InputStream,...) to represent the XML
586     * @param encoding the Char encoding that should be used to read from the stream
587     * @param validation use validation (true), or not (false)
588     * @param namespace use namespace awareness (true) , or not (false)
589     * @return a Document representing the same XML content in form of a DOM
590     * @throws org.w3c.dom.DOMException on Document problems
591     * @throws java.io.IOException on read problems
592     * @throws org.xml.sax.SAXException on parse problems
593     * @throws javax.xml.parsers.ParserConfigurationException
594     * if the underlying parser does
595     * @throws IllegalArgumentException if the provided InputSource or encoding is null
596     */

597    public static Document JavaDoc createDocument(final InputStream JavaDoc stream,
598                                          final String JavaDoc encoding,
599                                          final boolean validation,
600                                          final boolean namespace)
601       throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc, ParserConfigurationException JavaDoc
602    {
603
604       if (stream == null || encoding == null)
605       {
606          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
607       }
608
609       final InputSource JavaDoc in = new InputSource JavaDoc(new InputStreamReader JavaDoc(stream, encoding));
610
611       // use validation and/or name space awareness ?
612
return parseInputSource(in, validation, namespace, null, null);
613    }
614
615    /**
616     * create a Document from a reader representation of the XML content use the requested validation and name space
617     * awareness
618     *
619     * @param reader the reader pointing to the 'raw' xml
620     * @param namespace use namespace awareness (true) , or not (false)
621     * @param validation use validation (true), or not (false)
622     * @return a Document representing the same XML content in form of a DOM
623     * @throws org.w3c.dom.DOMException on Document problems
624     * @throws java.io.IOException if the reader doesn't allow successfull access
625     * @throws org.xml.sax.SAXException on parsing problems
626     * @throws javax.xml.parsers.ParserConfigurationException
627     * if the underlying parser does
628     */

629    public static Document JavaDoc createDocument(final Reader JavaDoc reader,
630                                          final boolean validation,
631                                          final boolean namespace)
632       throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc, ParserConfigurationException JavaDoc
633    {
634
635       if (reader == null)
636       {
637          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
638       }
639
640       final InputSource JavaDoc in = new InputSource JavaDoc(reader);
641
642       // use validation and/or name space awareness ?
643
return parseInputSource(in, validation, namespace, null, null);
644    }
645
646    /**
647     * create a Document from a URL (get the content from the URL); name space aware, but no validation
648     *
649     * @param documentURL the URL pointing to the Document
650     * @return a Document representing the document content
651     * @throws java.io.IOException on read problems
652     * @throws org.xml.sax.SAXException on parse problems
653     * @throws javax.xml.parsers.ParserConfigurationException
654     * if the underlying parser does
655     * @throws IllegalArgumentException if the provided URL is null
656     */

657    public static Document JavaDoc createDocument(final URL JavaDoc documentURL) throws IOException JavaDoc, SAXException JavaDoc,
658       ParserConfigurationException JavaDoc
659    {
660
661       if (documentURL == null)
662       {
663          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
664       }
665
666       InputStream JavaDoc in = null;
667
668       try
669       {
670          in = documentURL.openConnection().getInputStream();
671          return createDocument(in);
672       }
673       finally
674       {
675          if (in != null)
676          {
677             try
678             {
679                in.close();
680             }
681             catch (IOException JavaDoc ioe)
682             { /* ignore */
683             }
684          }
685       }
686    }
687
688    /**
689     * Creates a new Document from an InputSource allowing the validation, namespace, error handler and entity resolver
690     * to be set.
691     *
692     * @param inputSrc the InputSource representing the xml
693     * @param isValidating the boolean determining if validating is used against the xml
694     * @param isNamespaceAware the boolean determining if the NameSpaceAware feature is set
695     * @param errorHandler the ErrorHandler to be used if supplied
696     * @param entityResolver the entityResolver to be used if supplied
697     * @return a Document
698     * @throws org.w3c.dom.DOMException on Document problems
699     * @throws java.io.IOException on read problems
700     * @throws org.xml.sax.SAXException on parse problems
701     * @throws javax.xml.parsers.ParserConfigurationException
702     * if the underlying parser does
703     * @throws IllegalArgumentException if the provided InputSource is null
704     */

705    public static Document JavaDoc createDocument(final InputSource JavaDoc inputSrc,
706                                          final boolean isValidating,
707                                          final boolean isNamespaceAware,
708                                          final ErrorHandler JavaDoc errorHandler,
709                                          final EntityResolver JavaDoc entityResolver)
710       throws DOMException JavaDoc, IOException JavaDoc, SAXException JavaDoc, ParserConfigurationException JavaDoc
711    {
712
713       if (inputSrc == null)
714       {
715          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_INPUTSOURCE_ALLOWED));
716       }
717
718       return parseInputSource(inputSrc, isValidating, isNamespaceAware, errorHandler, entityResolver);
719    }
720
721    /**
722     * use a DocumentBuilder to parse the provided InputSource into a DOM Document
723     *
724     * @param in the InputSource to be parsed to a Document
725     * @param validation true if the Document should be validated (against DTD/Schema), false if not
726     * @param nameSpaceAware true if the Document should be name space aware, false if not
727     * @return the InputSource as a Document
728     * @throws org.xml.sax.SAXException on parse problems
729     * @throws java.io.IOException on read problems
730     * @throws javax.xml.parsers.ParserConfigurationException
731     *
732     */

733    private static Document JavaDoc parseInputSource(final InputSource JavaDoc in,
734                                             final boolean validation,
735                                             final boolean nameSpaceAware,
736                                             final ErrorHandler JavaDoc errorHandler,
737                                             final EntityResolver JavaDoc entityResolver)
738       throws SAXException JavaDoc, IOException JavaDoc, ParserConfigurationException JavaDoc
739    {
740
741       final DocumentBuilder JavaDoc parser = getBuilder(validation, nameSpaceAware);
742
743       // Set the ErrorHandler if provided
744
if (errorHandler != null)
745       {
746          parser.setErrorHandler(errorHandler);
747       }
748
749       // Set the EntityResolver if provided
750
if (entityResolver != null)
751       {
752          parser.setEntityResolver(entityResolver);
753       }
754       else
755       {
756          // When no entity resolver is specified and the parser is
757
// non-validating use the default non-validating entityResolver (to turn off issues with our DTD's ;)
758
if (!validation)
759          {
760 // +++TODO parser.setEntityResolver(new EboNonValidatingEntityResolver());
761
}
762       }
763
764       return parser.parse(in);
765    }
766
767    /**
768     * create a child node (to parentDocument) and populate it with the delivered content (if != null)
769     *
770     * @param parentDocument the Document that will receive the new Element and the content
771     * @param nodeName the name of the Element to create
772     * @param contentNode the Node that will be appended as a child to the created Element
773     * @return the created Node
774     * @throws IllegalArgumentException if the document or the node name is null
775     */

776    public static Node JavaDoc createDocumentRootNode(final Document JavaDoc parentDocument,
777                                              final String JavaDoc nodeName,
778                                              final Node JavaDoc contentNode)
779    {
780       return createDocumentRootNode(parentDocument, nodeName, contentNode, true);
781    }
782
783    /**
784     * create a child node (to parentDocument) and populate it with the delivered content (if != null).
785     *
786     * @param parentDocument the Document that will receive the new Element and the content
787     * @param nodeName the name of the Element to create
788     * @param contentNode the Node that will be imported (if external) or appended (if local) as a child to the
789     * created Element (incl. subtree)
790     * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
791     * imported (false), or if it can be appended (true)
792     * @return the created Element
793     * @throws IllegalArgumentException if the document or the node name is null
794     */

795    public static Node JavaDoc createDocumentRootNode(final Document JavaDoc parentDocument,
796                                              final String JavaDoc nodeName,
797                                              final Node JavaDoc contentNode,
798                                              final boolean contentIsLocal)
799    {
800
801       if (parentDocument == null || nodeName == null)
802       {
803          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_DOC_AND_NODE_ALLOWED));
804       }
805
806       Node JavaDoc el = null;
807
808       el = parentDocument.createElement(nodeName);
809
810       if (contentNode != null)
811       {
812          Node JavaDoc cNode = null;
813
814          if (contentIsLocal)
815          {
816             cNode = contentNode;
817          }
818          else
819          {
820             cNode = parentDocument.importNode(contentNode, true);
821          }
822
823          el.appendChild(cNode);
824       }
825
826       parentDocument.appendChild(el);
827
828       return el;
829    }
830
831    /**
832     * create a Node standalone (not added to any parent)
833     *
834     * @param document Document used to create the Element (not null!)
835     * @param nodeName name of the node to be created (not null!)
836     * @param contentNode content in form of a Node to be appended as child (if not null) ; including the subtree
837     * @return the newly created Node
838     * @throws IllegalArgumentException if the document or the node name is null
839     */

840    public static Node JavaDoc createNode(final Document JavaDoc document, final String JavaDoc nodeName, final Node JavaDoc contentNode)
841    {
842       return createNode(document, nodeName, contentNode, true);
843    }
844
845    /**
846     * create a Node standalone (not added to any parent)
847     *
848     * @param document Document used to create the Element (not null!)
849     * @param nodeName name of the node to be created (not null!)
850     * @param contentNode content in form of a Node to be imported or appended as child (if not null)
851     * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
852     * imported (false), or if it can be appended (true)
853     * @return the newly created Node
854     * @throws IllegalArgumentException if the document or the node name is null
855     */

856    public static Node JavaDoc createNode(final Document JavaDoc document,
857                                  final String JavaDoc nodeName,
858                                  final Node JavaDoc contentNode,
859                                  final boolean contentIsLocal)
860    {
861
862       if (document == null || nodeName == null)
863       {
864          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_DOC_AND_NODE_ALLOWED));
865       }
866
867       Node JavaDoc el = null;
868
869       el = document.createElement(nodeName);
870
871       if (contentNode != null)
872       {
873          Node JavaDoc cNode = null;
874
875          if (contentIsLocal)
876          {
877             cNode = contentNode;
878          }
879          else
880          {
881             cNode = document.importNode(contentNode, true);
882          }
883
884          el.appendChild(cNode);
885       }
886
887       return el;
888    }
889
890    /**
891     * create a child node (to parentNode) and populate it with the delivered content (if != null)
892     *
893     * @param parentNode the parent Node (not null!)
894     * @param nodeName the name for the new Element (not null!)
895     * @param contentNode org.w3c.dom.Node that contains the content to be appended (incl. subtree) to the parent
896     * Document (or null)
897     * @return the newly created Node
898     * @throws IllegalArgumentException if the parent node or the node name is null
899     */

900    public static Node JavaDoc createChildNode(final Node JavaDoc parentNode, final String JavaDoc nodeName, final Node JavaDoc contentNode)
901    {
902       return createChildNode(parentNode, nodeName, contentNode, true);
903    }
904
905    /**
906     * create a child node (to parentNode) and populate it with the delivered content (if != null)
907     *
908     * @param parentNode the parent Node (not null!)
909     * @param nodeName the name for the new Element (not null!)
910     * @param contentNode org.w3c.dom.Node that contains the content to be imported (incl. subtree) or appended (if
911     * local) to the parent Document (or null)
912     * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
913     * imported (false), or if it can be appended (true)
914     * @return the newly created Node
915     * @throws IllegalArgumentException if the parent node or the node name is null
916     */

917    public static Node JavaDoc createChildNode(final Node JavaDoc parentNode,
918                                       final String JavaDoc nodeName,
919                                       final Node JavaDoc contentNode,
920                                       final boolean contentIsLocal)
921    {
922
923       if (parentNode == null || nodeName == null)
924       {
925          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_PARENT_AND_NODE_ALLOWED));
926       }
927
928       if (parentNode.getNodeType() != Node.DOCUMENT_NODE && parentNode.getOwnerDocument() == null)
929       {
930          throw new IllegalArgumentException JavaDoc((ERR_WRONG_NODETYPE));
931       }
932
933       Node JavaDoc el = null;
934
935       if (parentNode.getNodeType() == Node.DOCUMENT_NODE)
936       {
937          el = ((Document JavaDoc)parentNode).createElement(nodeName);
938       }
939       else
940       {
941          el = parentNode.getOwnerDocument().createElement(nodeName);
942       }
943
944       parentNode.appendChild(el);
945
946       if (contentNode != null)
947       {
948          Node JavaDoc cNode = null;
949
950          if (contentIsLocal)
951          {
952             cNode = contentNode;
953          }
954          else
955          {
956             cNode = parentNode.getOwnerDocument().importNode(contentNode, true);
957          }
958
959          el.appendChild(cNode);
960       }
961
962       return el;
963    }
964
965    /**
966     * Create a child node and append it to the provided parent node
967     *
968     * @param nodeName the name for the new node
969     * @param parentNode the parent org.w3c.dom.Node that will receive the child
970     * @return the newly created Node
971     * @throws IllegalArgumentException if the parent node or the node name is null
972     */

973    public static Node JavaDoc createChildNode(final Node JavaDoc parentNode, final String JavaDoc nodeName)
974    {
975       return createChildNode(parentNode, nodeName, null, true);
976    }
977
978    /**
979     * create a text node
980     * <p/>
981     * To create a stand-alone node, pass null for parentNode. Otherwise the node will be created as a child of
982     * parentNode.
983     *
984     * @param doc the Document to contain the new text node (not null!)
985     * @param parentNode the Node under which the new text node should be placed (or null)
986     * @param nodeName the name of the new text node (not null!)
987     * @param content the text itself
988     * @return the newly created Node
989     * @throws IllegalArgumentException if either the document, or the node name and the parent node are null
990     */

991    public static Node JavaDoc createTextNode(final Document JavaDoc doc,
992                                      final Node JavaDoc parentNode,
993                                      final String JavaDoc nodeName,
994                                      final String JavaDoc content)
995    {
996
997       if (doc == null || (nodeName == null && parentNode == null))
998       {
999          throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_DOC_OR_PARENT_AND_NODE_ALLOWED));
1000      }
1001
1002      Node JavaDoc el = null;
1003
1004      if (nodeName != null)
1005      {
1006         el = doc.createElement(nodeName);
1007
1008         if (parentNode != null)
1009         {
1010            parentNode.appendChild(el);
1011         }
1012      }
1013      else
1014      {
1015         el = parentNode;
1016      }
1017
1018      if (content != null)
1019      {
1020         el.appendChild(doc.createTextNode(content));
1021      }
1022
1023      return el;
1024   }
1025
1026   /**
1027    * Create a text node as a child of another node.
1028    *
1029    * @param parentNode the Node under which the new text node should be placed (not null!)
1030    * @param nodeName the name of the new text node (not null!)
1031    * @param content the text itself
1032    * @return the newly created Node
1033    * @throws IllegalArgumentException if the parent node is null
1034    */

1035   public static Node JavaDoc createTextNode(final Node JavaDoc parentNode, final String JavaDoc nodeName, final String JavaDoc content)
1036   {
1037
1038      if (parentNode == null)
1039      {
1040         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_PARENT_NODE_ALLOWED));
1041      }
1042
1043      return createTextNode(parentNode.getOwnerDocument(), parentNode, nodeName, content);
1044   }
1045
1046   /**
1047    * create an attribute and add it to the Node provided
1048    *
1049    * @param el the element that will receive the attribute (not null!)
1050    * @param attributeName name of the attribute to be created (not null!)
1051    * @param attributeValue value of the attribute to be created
1052    * @return the created attribute as Attr
1053    * @throws IllegalArgumentException if the element or the attribute name is null
1054    */

1055   public static Attr JavaDoc createAttribute(final Element JavaDoc el, final String JavaDoc attributeName, final String JavaDoc attributeValue)
1056   {
1057
1058      if (el == null || attributeName == null)
1059      {
1060         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_NODE_AND_ATTNAME_ALLOWED));
1061      }
1062
1063      final Attr JavaDoc at = el.getOwnerDocument().createAttribute(attributeName);
1064
1065      if (attributeValue != null)
1066      {
1067         at.setValue(attributeValue);
1068      }
1069
1070      el.setAttributeNode(at);
1071
1072      return at;
1073   }
1074
1075   /**
1076    * create an attribute standalone (not added to any node)
1077    *
1078    * @param doc the Document used to create the attribute
1079    * @param attributeName name of the attribute to be created
1080    * @param attributeValue value of the attribute to be created
1081    * @return the Attribute as org.w3c.dom.Attr
1082    * @throws IllegalArgumentException if the document or the attribute name is null
1083    */

1084   public static Attr JavaDoc createAttribute(final Document JavaDoc doc, final String JavaDoc attributeName, final String JavaDoc attributeValue)
1085   {
1086
1087      if (doc == null || attributeName == null)
1088      {
1089         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_DOC_AND_ATTNAME_ALLOWED));
1090      }
1091
1092      final Attr JavaDoc at = doc.createAttribute(attributeName);
1093      at.setValue(attributeValue);
1094
1095      return at;
1096   }
1097
1098   /**
1099    * get the value of an attribute of a node (if present)
1100    *
1101    * @param attributeName the name of the attribute you want to get
1102    * @param node the Node where the attribute lives
1103    * @return the value of the attribute, or null if not present
1104    * @throws IllegalArgumentException if the attribute name or the node is null
1105    */

1106   public static String JavaDoc getAttributeValue(final String JavaDoc attributeName, final Node JavaDoc node)
1107   {
1108
1109      if (attributeName == null || node == null)
1110      {
1111         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_NODE_AND_ATTNAME_ALLOWED));
1112      }
1113
1114      final org.w3c.dom.NamedNodeMap JavaDoc attribMap = node.getAttributes();
1115
1116      if (attribMap != null && attribMap.getLength() > 0)
1117      {
1118         final Node JavaDoc n = attribMap.getNamedItem(attributeName);
1119
1120         if (n != null)
1121         {
1122            return n.getNodeValue();
1123         }
1124      }
1125
1126      return null;
1127   }
1128
1129   /**
1130    * get an attribute of a node (if present)
1131    *
1132    * @param attributeName the name of the attribute you want to get
1133    * @param node the Node where the attribute lives
1134    * @return the attribute, or null if not present on the node
1135    * @throws IllegalArgumentException if the attribute name or the node is null
1136    */

1137   public static Attr JavaDoc getAttribute(final String JavaDoc attributeName, final Node JavaDoc node)
1138   {
1139
1140      if (attributeName == null || node == null)
1141      {
1142         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_NODE_AND_ATTNAME_ALLOWED));
1143      }
1144
1145      final org.w3c.dom.NamedNodeMap JavaDoc attribMap = node.getAttributes();
1146
1147      if (attribMap != null && attribMap.getLength() > 0)
1148      {
1149         final Node JavaDoc n = attribMap.getNamedItem(attributeName);
1150
1151         if (n != null)
1152         {
1153            return (Attr JavaDoc)n;
1154         }
1155      }
1156
1157      return null;
1158   }
1159
1160   /**
1161    * get the text from an elements body example get 'hello world' from <someelem>hello world</someelem>
1162    *
1163    * @param parentNode the node that contains text
1164    * @return the text inside the element and end element tags if the node is a text node, otherwise an empty string
1165    * @throws org.w3c.dom.DOMException if the undelying DOM api does
1166    */

1167   public static String JavaDoc getElementBodyText(final Node JavaDoc parentNode)
1168   {
1169
1170      final Node JavaDoc textNode = parentNode.getFirstChild();
1171
1172      if (textNode != null && Node.TEXT_NODE == textNode.getNodeType())
1173      {
1174         return textNode.getNodeValue();
1175      }
1176
1177      return "";
1178   }
1179
1180   /**
1181    * create a CDATA section as a child to the provided parentNode In case the content is null, a child node without
1182    * content will be created, using createChildNode()
1183    *
1184    * @param parentNode Node (parent) of the element to be created (not null!)
1185    * @param nodeName the name you want to give your Node (or null if the textnode should be appended to the parent
1186    * node directly)
1187    * @param content the content of the node (the text that will be wrapped in a CDATA section)
1188    * @return the org.w3c.dom.Node that was created
1189    * @throws IllegalArgumentException if the parent node is null
1190    * @see #createChildNode(org.w3c.dom.Node,String)
1191    */

1192   public static Node JavaDoc createCDATANode(final Node JavaDoc parentNode, final String JavaDoc nodeName, final String JavaDoc content)
1193   {
1194
1195      if (parentNode == null)
1196      {
1197         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_PARENT_AND_CONTENT_ALLOWED));
1198      }
1199
1200      if (content == null)
1201      {
1202         return createChildNode(parentNode, nodeName);
1203      }
1204
1205      Node JavaDoc el = null;
1206
1207      if (nodeName != null)
1208      {
1209         el = parentNode.getOwnerDocument().createElement(nodeName);
1210         parentNode.appendChild(el);
1211
1212      }
1213      else
1214      {
1215         el = parentNode;
1216      }
1217
1218      el.appendChild(parentNode.getOwnerDocument().createCDATASection(content));
1219
1220      return el;
1221   }
1222
1223   /**
1224    * create a new Element with nodeName and insert it before the siblingNode (same level)
1225    *
1226    * @param siblingNode the node that will be used as reference; the new element will be inserted before this node
1227    * @param nodeName the name of the element to create
1228    * @param content any subtree that will be appended as child of the new element (if != null)
1229    * @return the newly created element as a Node
1230    * @throws IllegalArgumentException if the sibling node or the node name is null
1231    */

1232   public static Node JavaDoc addNodeBeforeSibling(final Node JavaDoc siblingNode, final String JavaDoc nodeName, final Node JavaDoc content)
1233   {
1234      return addNodeBeforeSibling(siblingNode, nodeName, content, true);
1235   }
1236
1237   /**
1238    * Create a new Element with nodeName and insert it before the siblingNode (same level). If the node name is null,
1239    * insert the content node before the sibling node. Best way to use this method is with either a nodeName or content,
1240    * but not both.
1241    *
1242    * @param siblingNode the node that will be used as reference; the new element will be inserted before this node
1243    * @param nodeName the name of the element to create (or null; if null, content needs to be not null!)
1244    * @param content any subtree that will be imported or appended (if local) as child of the new element (if !=
1245    * null)
1246    * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
1247    * imported (false), or if it can be appended (true)
1248    * @return the newly created element as a Node
1249    * @throws IllegalArgumentException if the sibling node is null or the node name and the content is null
1250    */

1251   public static Node JavaDoc addNodeBeforeSibling(final Node JavaDoc siblingNode,
1252                                           final String JavaDoc nodeName,
1253                                           final Node JavaDoc content,
1254                                           final boolean contentIsLocal)
1255   {
1256
1257      if (siblingNode == null || (nodeName == null && content == null))
1258      {
1259         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_SIBLING_AND_NODE_ALLOWED));
1260      }
1261
1262      Node JavaDoc el = null;
1263
1264      if (nodeName != null)
1265      {
1266         // if a node name was presented, create a node with that name and insert it before the sibling
1267
el = siblingNode.getOwnerDocument().createElement(nodeName);
1268         siblingNode.getParentNode().insertBefore(el, siblingNode);
1269      }
1270
1271      if (content != null)
1272      {
1273
1274         Node JavaDoc cNode = null;
1275
1276         if (contentIsLocal)
1277         {
1278            cNode = content;
1279         }
1280         else
1281         {
1282            // if the node is not part of the local document, import it first
1283
cNode = siblingNode.getOwnerDocument().importNode(content, true);
1284         }
1285
1286         if (el != null)
1287         {
1288            el.appendChild(cNode);
1289         }
1290         else
1291         {
1292            // no node was created, insert the content directly before the sibling
1293
el = siblingNode.getParentNode().insertBefore(cNode, siblingNode);
1294         }
1295      }
1296
1297      return el;
1298   }
1299
1300   /**
1301    * create a new Element with nodeName and insert it after the siblingNode (same level); if the node name is null,
1302    * insert the content node after the sibling node; both Nodes need to be part of the same document
1303    *
1304    * @param siblingNode the node that will be used as reference; the new element will be inserted after this node
1305    * @param nodeName the name of the element to create (or null; if null, content needs to be not null!)
1306    * @param content any subtree that will be imported or appended (if local) as child of the new element (if !=
1307    * null)
1308    * @return the newly created element as a Node
1309    * @throws IllegalArgumentException if the sibling node is null or the node name and the content is null
1310    */

1311   public static Node JavaDoc addNodeAfterSibling(final Node JavaDoc siblingNode, final String JavaDoc nodeName, final Node JavaDoc content)
1312   {
1313      return addNodeAfterSibling(siblingNode, nodeName, content, true);
1314   }
1315
1316   /**
1317    * create a new Element with nodeName and insert it after the siblingNode (same level); if the node name is null,
1318    * insert the content node after the sibling node
1319    *
1320    * @param siblingNode the node that will be used as reference; the new element will be inserted after this node
1321    * @param nodeName the name of the element to create (or null; if null, content needs to be not null!)
1322    * @param content any subtree that will be imported or appended (if local) as child of the new element (if !=
1323    * null)
1324    * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
1325    * imported (false), or if it can be appended (true)
1326    * @return the newly created element as a Node
1327    * @throws IllegalArgumentException if the sibling node is null or the node name and the content is null
1328    */

1329   public static Node JavaDoc addNodeAfterSibling(final Node JavaDoc siblingNode,
1330                                          final String JavaDoc nodeName,
1331                                          final Node JavaDoc content,
1332                                          final boolean contentIsLocal)
1333   {
1334
1335      if (siblingNode == null || (nodeName == null && content == null))
1336      {
1337         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_SIBLING_AND_NODE_ALLOWED));
1338      }
1339
1340      Node JavaDoc el = null;
1341      Node JavaDoc cNode = null;
1342
1343      if (content != null)
1344      {
1345
1346         if (contentIsLocal)
1347         {
1348            cNode = content;
1349         }
1350         else
1351         {
1352            cNode = siblingNode.getOwnerDocument().importNode(content, true);
1353         }
1354      }
1355
1356      if (nodeName != null)
1357      {
1358         el = siblingNode.getOwnerDocument().createElement(nodeName);
1359
1360         if (cNode != null)
1361         {
1362            el.appendChild(cNode);
1363         }
1364      }
1365
1366      final Node JavaDoc nextSibling = siblingNode.getNextSibling();
1367
1368      if (nextSibling == null)
1369      {
1370         if (el != null)
1371         {
1372            siblingNode.getParentNode().appendChild(el);
1373         }
1374         else
1375         {
1376            // check for null is not necessary here because
1377
// this condition would have produced an IllegalArgumentException
1378
el = siblingNode.getParentNode().appendChild(cNode);
1379         }
1380
1381      }
1382      else
1383      {
1384         if (el != null)
1385         {
1386            siblingNode.getParentNode().insertBefore(el, nextSibling);
1387         }
1388         else
1389         {
1390            // check for null is not necessary here because this condition would
1391
// have produced an IllegalArgumentException
1392
el = siblingNode.getParentNode().insertBefore(cNode, nextSibling);
1393         }
1394      }
1395
1396      return el;
1397   }
1398
1399   /**
1400    * Create and adds a new element to parent with a tag of key.
1401    *
1402    * @param document xml document to which element will be added
1403    * @param parent Element inside of which element of tag "key" will go.
1404    * @param key String that becomes the appended element.
1405    * @return new element appended to parent.
1406    */

1407   public static Element JavaDoc appendChildElement(final Document JavaDoc document, final Element JavaDoc parent, final String JavaDoc key)
1408   {
1409      final Element JavaDoc element = document.createElement(key);
1410      parent.appendChild(element);
1411
1412      return element;
1413   }
1414
1415   /**
1416    * import a node into the current document directly under the passed parent Node
1417    *
1418    * @param parentNode the Node under which the content should be placed (not null!)
1419    * @param contentNode the Node (not null!) that will be imported as a child to the created Node (incl. subtree)
1420    * @return the Node representing the imported content in the current dom
1421    * @throws IllegalArgumentException if the parent node or the content node is null
1422    */

1423   public static Node JavaDoc appendChildNode(final Node JavaDoc parentNode, final Node JavaDoc contentNode)
1424   {
1425      return appendChildNode(parentNode, contentNode, true);
1426   }
1427
1428   /**
1429    * import a node into the current document directly under the passed parent Node
1430    *
1431    * @param parentNode the Node under which the content should be placed (not null!)
1432    * @param contentNode the Node (not null!) that will be imported as a child to the created Node (incl. subtree)
1433    * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
1434    * imported (false), or if it can be appended (true)
1435    * @return the Node representing the imported content in the current dom (or the passed in contentNode if it's
1436    * local)
1437    * @throws IllegalArgumentException if the parent node or the content node is null
1438    */

1439   public static Node JavaDoc appendChildNode(final Node JavaDoc parentNode, final Node JavaDoc contentNode, final boolean contentIsLocal)
1440   {
1441
1442      if (parentNode == null || contentNode == null)
1443      {
1444         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_PARENT_AND_CONTENT_ALLOWED));
1445      }
1446
1447      Node JavaDoc cNode = null;
1448
1449      if (contentIsLocal)
1450      {
1451         cNode = contentNode;
1452      }
1453      else
1454      {
1455         cNode = parentNode.getOwnerDocument().importNode(contentNode, true);
1456      }
1457
1458      parentNode.appendChild(cNode);
1459
1460      return cNode;
1461   }
1462
1463   /**
1464    * Deep copies the src Node's children to the dest Node. It is assumed that the src and dest node exist in different
1465    * Documents, and so the nodes are first imported into the dest doc before adding them.
1466    *
1467    * @param src Node in Document A that should have all it's children copied.
1468    * @param dest Node in Document B that is the destination of the copy from the src node.
1469    * @throws IllegalArgumentException if the provided nodes are null
1470    */

1471   public static void importChildNodes(final Node JavaDoc src, final Node JavaDoc dest)
1472   {
1473      appendChildNodes(src, dest, false);
1474   }
1475
1476   /**
1477    * Move all child nodes or src to the dest node. It is assumed that both nodes are in the same document
1478    *
1479    * @param src Node that should have all it's children removed.
1480    * @param dest Node that is the destination of the move from the src node.
1481    * @throws IllegalArgumentException if the provided nodes are null
1482    */

1483   public static void moveChildNodes(final Node JavaDoc src, final Node JavaDoc dest)
1484   {
1485      appendChildNodes(src, dest, true);
1486   }
1487
1488   /**
1489    * Deep copies the src Node's children to the dest Node. If contentIsLocal is false, it is assumed that the src and
1490    * dest node exist in different Documents, and so the nodes are first imported into the dest doc before adding them.
1491    *
1492    * @param src Node in Document A that should have all it's children copied.
1493    * @param dest Node in Document B that is the destination of the copy from the src node.
1494    * @param contentIsLocal a boolean indicating wether the contentNode is external to the document and has to be
1495    * imported (false), or if it can be appended (true) in which case the nodes are moved from the
1496    * src node to the dest node
1497    * @throws IllegalArgumentException if the provided nodes are null, or if contentIsLocal is false and src and dest
1498    * are in the same document
1499    */

1500   private static void appendChildNodes(final Node JavaDoc src, final Node JavaDoc dest, final boolean contentIsLocal)
1501   {
1502
1503      if (src == null || dest == null)
1504      {
1505         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1506      }
1507
1508      if (!contentIsLocal && src.getOwnerDocument().equals(dest.getOwnerDocument()))
1509      {
1510         throw new IllegalArgumentException JavaDoc((ERR_SRC_AND_DEST_DOC_EQUAL));
1511      }
1512
1513      final NodeList JavaDoc nodesToImport = src.getChildNodes();
1514      for (int i = 0; i < nodesToImport.getLength(); i++)
1515      {
1516         Node JavaDoc singleNode = null;
1517
1518         if (!contentIsLocal)
1519         {
1520            singleNode = dest.getOwnerDocument().importNode(nodesToImport.item(i), true);
1521         }
1522         else
1523         {
1524            singleNode = nodesToImport.item(i);
1525         }
1526         dest.appendChild(singleNode);
1527      }
1528   }
1529
1530   /**
1531    * create the output properties for an xsl style sheet (like <xsl:output method='xml' ... />)
1532    *
1533    * @param omitXMLDeclaration omit-xml-declaration 'yes' or 'no'
1534    * @param enableIndenting indent 'yes' or 'no'
1535    * @param elements cdata-section-elements will be converted to a space separated list
1536    * @return the properties object to pass to the Transformer
1537    * @see javax.xml.transform.Transformer #setOutputProperties(Properties)
1538    * @see javax.xml.transform.OutputKeys
1539    * @see java.util.Properties
1540    */

1541   public static Properties JavaDoc createOutputProperties(final boolean omitXMLDeclaration,
1542                                                   final boolean enableIndenting,
1543                                                   final String JavaDoc[] elements)
1544   {
1545      //Set the properties for the transformation
1546
final Properties JavaDoc oprops = new Properties JavaDoc();
1547
1548      oprops.put(ATTRIB_METHOD, "xml");
1549      oprops.put(ATTRIB_OMIT_XML_DECLARATION, omitXMLDeclaration ? PARAM_YES : PARAM_NO);
1550      oprops.put(ATTRIB_INDENT, enableIndenting ? PARAM_YES : PARAM_NO);
1551
1552      if (elements != null)
1553      {
1554         //Make the element array a space delimited string
1555
final StringBuffer JavaDoc list = new StringBuffer JavaDoc();
1556         for (int i = 0; i < elements.length; i++)
1557         {
1558            list.append(" ").append(elements[i]);
1559         }
1560
1561         oprops.put(ATTRIB_CDATA_SECTION_ELEMENTS, list.toString());
1562      }
1563
1564      return oprops;
1565   }
1566
1567   /**
1568    * serialize a Document to the provided OutputStream (using a Transformer)
1569    *
1570    * @param doc Document (-fragment) to be serialized
1571    * @param output the OutputStream to write to
1572    * @throws java.io.IOException on read problems
1573    * @throws javax.xml.transform.TransformerConfigurationException
1574    * on parser configuration problems
1575    * @throws javax.xml.transform.TransformerException
1576    * on trandformation problems
1577    * @throws IllegalArgumentException if the output stream or the document is null
1578    */

1579   public static void serialize(final Node JavaDoc doc,
1580                                final java.io.OutputStream JavaDoc output)
1581      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1582   {
1583
1584      if (output == null || doc == null)
1585      {
1586         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1587      }
1588
1589      final Transformer JavaDoc t = getTransformer();
1590
1591      serialize(doc, output, t);
1592   }
1593
1594   /**
1595    * serialize a Document to the provided OutputStream (using the passed Transformer)
1596    *
1597    * @param doc Document (-fragment) to be serialized
1598    * @param output the OutputStream to write to
1599    * @param transformer the transformer to use
1600    * @throws java.io.IOException on read problems
1601    * @throws javax.xml.transform.TransformerConfigurationException
1602    * on transformer configuration problems
1603    * @throws javax.xml.transform.TransformerException
1604    * on trnaformation problems
1605    * @throws IllegalArgumentException if the output stream or the document or the transformer is null
1606    */

1607   public static void serialize(final Node JavaDoc doc,
1608                                final java.io.OutputStream JavaDoc output,
1609                                final Transformer JavaDoc transformer)
1610      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1611   {
1612
1613      if (output == null || doc == null || transformer == null)
1614      {
1615         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1616      }
1617
1618      transformer.transform(new DOMSource JavaDoc(doc), new StreamResult JavaDoc(output));
1619      output.flush();
1620
1621      return;
1622   }
1623
1624   /**
1625    * serialize a Document to the provided Writer (using a Transformer)
1626    *
1627    * @param doc Document (-fragment) to be serialized
1628    * @param writer the writer to write to
1629    * @throws java.io.IOException on read problems
1630    * @throws javax.xml.transform.TransformerConfigurationException
1631    * on transformer configuration problems
1632    * @throws javax.xml.transform.TransformerException
1633    * on trnaformation problems
1634    * @throws IllegalArgumentException if the document or the writer is null
1635    */

1636   public static void serialize(final Node JavaDoc doc, final Writer JavaDoc writer)
1637      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1638   {
1639
1640      if (writer == null || doc == null)
1641      {
1642         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1643      }
1644
1645      final Transformer JavaDoc t = getTransformer();
1646      serialize(doc, writer, t);
1647   }
1648
1649   /**
1650    * serialize a Document to the provided Writer (using a Transformer) This call uses the transformer's output encoding
1651    * to convert the content to a String (default is UTF-8)
1652    *
1653    * @param doc Document (-fragment) to be serialized
1654    * @param writer the writer to write to
1655    * @param transformer the transformer to use
1656    * @throws java.io.IOException on read problems
1657    * @throws javax.xml.transform.TransformerConfigurationException
1658    * on transformer configuration problems
1659    * @throws javax.xml.transform.TransformerException
1660    * on trnaformation problems
1661    * @throws IllegalArgumentException if the document or the writer or the transformer is null
1662    */

1663   public static void serialize(final Node JavaDoc doc, final Writer JavaDoc writer, final Transformer JavaDoc transformer)
1664      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1665   {
1666
1667      if (writer == null || doc == null || transformer == null)
1668      {
1669         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1670      }
1671
1672      final String JavaDoc result = serialize(doc, transformer);
1673
1674      writer.write(result);
1675   }
1676
1677   /**
1678    * serialize a Document to String (using a Transformer) This call uses a javax.xml.transform.Transformer, and it's
1679    * output encoding to convert the content to a String (default is UTF-8). If you want to use a different encoding,
1680    * get a transformer via #getTransformer(Properties) and set the output property "encoding" to the desired one, then
1681    * use #serialize(Node, Transformer)
1682    *
1683    * @param doc Document (-fragment) to be serialized
1684    * @return the String representation of the Document
1685    * @throws java.io.IOException on read problems
1686    * @throws javax.xml.transform.TransformerConfigurationException
1687    * on transformer configuration problems
1688    * @throws javax.xml.transform.TransformerException
1689    * on trnaformation problems
1690    * @throws IllegalArgumentException if the document is null
1691    */

1692   public static String JavaDoc serialize(final Node JavaDoc doc)
1693      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1694   {
1695
1696      if (doc == null)
1697      {
1698         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1699      }
1700
1701      //Serialize the document using a transformer
1702
final Transformer JavaDoc t = getTransformer();
1703
1704      return serialize(doc, t);
1705   }
1706
1707   /**
1708    * serialize a Document to String (using the passed Transformer) This call uses the transformer's output encoding to
1709    * convert the content to a String
1710    *
1711    * @param doc Document (-fragment) to be serialized
1712    * @param transformer the transformer to use
1713    * @return the String representation of the Document
1714    * @throws java.io.IOException on read problems
1715    * @throws javax.xml.transform.TransformerConfigurationException
1716    * on transformer configuration problems
1717    * @throws javax.xml.transform.TransformerException
1718    * on trnaformation problems
1719    * @throws IllegalArgumentException if the document or the transformer is null
1720    */

1721   public static String JavaDoc serialize(final Node JavaDoc doc, final Transformer JavaDoc transformer)
1722      throws IOException JavaDoc, TransformerConfigurationException JavaDoc, TransformerException JavaDoc
1723   {
1724
1725      if (doc == null || transformer == null)
1726      {
1727         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1728      }
1729
1730      //Serialize the Node using a transformer
1731
final ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
1732      transformer.transform(new DOMSource JavaDoc(doc), new StreamResult JavaDoc(baos));
1733
1734      final String JavaDoc resultEncoding = transformer.getOutputProperties().getProperty("encoding");
1735
1736      return baos.toString((resultEncoding == null ? "UTF-8" : resultEncoding));
1737   }
1738
1739   /**
1740    * Add an xsl:import or xsl:include etc. node to an existing xsl style sheet (represented as DOM)
1741    *
1742    * @param xslDom the DOM representation of the XSL style sheet
1743    * @param directiveName the tag name (@see #DIRECTIVE_INCLUDE and #DIRECTIVE_IMPORT)
1744    * @param attributeName the name of an attribute to create, or null
1745    * @param attributeValue the value for the attribute, or null
1746    * @return the newly created node
1747    * @throws javax.xml.transform.TransformerException
1748    * when problems adding the xsl directive occur
1749    * @throws IllegalArgumentException if the document or the directive name is null, or if the document is not an xsl
1750    * style sheet
1751    */

1752   public static Node JavaDoc addDirectiveToXSL(final Document JavaDoc xslDom,
1753                                        final String JavaDoc directiveName,
1754                                        final String JavaDoc attributeName,
1755                                        String JavaDoc attributeValue)
1756      throws TransformerException JavaDoc
1757   {
1758
1759      if (xslDom == null || directiveName == null)
1760      {
1761         // The style dom does NOT have a <xsl:stylesheet> node - can't do anything
1762
throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_DOC_AND_DIRECTIVENAME_ALLOWED));
1763      }
1764
1765      // Get the 'xsl:stylesheet' node
1766
final Node JavaDoc styleSheetNode = new CachedXPathAPI().selectSingleNode(xslDom.getDocumentElement(),
1767         "//xsl:stylesheet");
1768
1769      if (styleSheetNode == null)
1770      {
1771         // The style dom does NOT have a <xsl:stylesheet> node - can't do anything
1772
throw new IllegalArgumentException JavaDoc((ERR_IS_NOT_A_STYLESHEET));
1773      }
1774
1775      // Get the first child node of the xsl:stylesheet node
1776
final Node JavaDoc firstChild = styleSheetNode.getFirstChild();
1777
1778      Node JavaDoc directiveNode = null;
1779
1780      if (firstChild == null)
1781      {
1782         directiveNode = createChildNode(styleSheetNode, directiveName);
1783      }
1784      else
1785      {
1786         directiveNode = addNodeBeforeSibling(firstChild, directiveName, null);
1787      }
1788
1789      if (attributeName != null)
1790      {
1791         attributeValue = attributeValue == null ? "" : attributeValue;
1792         createAttribute((Element JavaDoc)directiveNode, attributeName, attributeValue);
1793      }
1794
1795      return directiveNode;
1796   }
1797
1798   /**
1799    * Add an xsl:import or xsl:include node to an existing xsl style sheet (represented as DOM) before the passed
1800    * sibling node.
1801    *
1802    * @param sibling the node before which the new node will be added as a sibling (same level)
1803    * @param directiveName (@see #DIRECTIVE_INCLUDE and #DIRECTIVE_IMPORT)
1804    * @param attributeName the name of an attribute to create, or null
1805    * @param attributeValue the value for the attribute, or null
1806    * @return the newly created node
1807    * @throws IllegalArgumentException if the sibling node or the directive name is null (no check if this is a style
1808    * sheet!)
1809    */

1810   public static Node JavaDoc addDirectiveToXSLBeforeSibling(final Node JavaDoc sibling,
1811                                                     final String JavaDoc directiveName,
1812                                                     final String JavaDoc attributeName,
1813                                                     String JavaDoc attributeValue)
1814   {
1815
1816      if (sibling == null || directiveName == null)
1817      {
1818         // The style dom does NOT have a <xsl:stylesheet> node - can't do anything
1819
throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
1820      }
1821
1822      final Node JavaDoc directiveNode = addNodeBeforeSibling(sibling, directiveName, null);
1823
1824      if (attributeName != null)
1825      {
1826         attributeValue = attributeValue == null ? "" : attributeValue;
1827         createAttribute((Element JavaDoc)directiveNode, attributeName, attributeValue);
1828      }
1829
1830      return directiveNode;
1831   }
1832
1833   /**
1834    * Transforms an xml with the provided xsl document and writes it to the writer.
1835    *
1836    * @param contentDom the document to be transformed
1837    * @param styleDom the style to apply to the content
1838    * @param out the writer to write the result to
1839    * @throws javax.xml.transform.TransformerException
1840    * on trnaformation problems
1841    * @throws javax.xml.transform.TransformerConfigurationException
1842    * on transformer configuration problems
1843    * @throws java.io.FileNotFoundException if the write operation fails
1844    * @throws java.io.IOException on read problems
1845    * @throws IllegalArgumentException if any of the arguments is null
1846    */

1847   public static void xslTransform(final Document JavaDoc contentDom,
1848                                   final Document JavaDoc styleDom,
1849                                   final Writer JavaDoc out)
1850      throws TransformerException JavaDoc, TransformerConfigurationException JavaDoc, FileNotFoundException JavaDoc, IOException JavaDoc
1851   {
1852      getTransformer(styleDom).transform(new DOMSource JavaDoc(contentDom), new StreamResult JavaDoc(out));
1853   }
1854
1855   /**
1856    * Transforms an xml document with the provided xsl style (compiled version) and write it to the provided writer
1857    *
1858    * @param contentDom the document to be transformed
1859    * @param transformer the compiled xsl style sheet that will be applied to the content document
1860    * @param out the OutputStream to write the result to
1861    * @return the encoding in which to read from the stream (taken from the transformers encoding property) <p>Note: you
1862    * can set that encoding via #Transformer.getOutputProperties().setProperty("encoding", String); or in you
1863    * xsl style sheet via xsl:output encoding="your encoding here" .....; the default encoding is UTF-8</p>
1864    * @throws javax.xml.transform.TransformerException
1865    * if the transformation fails
1866    * @throws javax.xml.transform.TransformerConfigurationException
1867    * if the transformer is misconfigured
1868    * @throws IllegalArgumentException if any of the arguments is null
1869    */

1870   public static String JavaDoc xslTransform(final Document JavaDoc contentDom,
1871                                     final Transformer JavaDoc transformer,
1872                                     final OutputStream JavaDoc out)
1873      throws TransformerException JavaDoc, TransformerConfigurationException JavaDoc
1874   {
1875      transformer.transform(new DOMSource JavaDoc(contentDom), new StreamResult JavaDoc(out));
1876
1877      return transformer.getOutputProperties().getProperty("encoding");
1878   }
1879
1880   /**
1881    * Transforms an xml document with the provided xsl style (compiled version) and write it to the provided writer
1882    *
1883    * @param contentDom the document to be transformed
1884    * @param transformer the compiled xsl style sheet that will be applied to the content document
1885    * @param writer the writer to write the result to
1886    * @throws javax.xml.transform.TransformerException
1887    * if the transformation fails
1888    * @throws javax.xml.transform.TransformerConfigurationException
1889    * if the transformer is misconfigured
1890    * @throws IllegalArgumentException if any of the arguments is null
1891    */

1892   public static void xslTransform(final Document JavaDoc contentDom,
1893                                   final Transformer JavaDoc transformer,
1894                                   final Writer JavaDoc writer)
1895      throws TransformerException JavaDoc, TransformerConfigurationException JavaDoc
1896   {
1897      transformer.transform(new DOMSource JavaDoc(contentDom), new StreamResult JavaDoc(writer));
1898   }
1899
1900   /**
1901    * get a new Transformer from the TransformerFactory with indent turned on
1902    *
1903    * @return the new Transformer
1904    * @throws javax.xml.transform.TransformerConfigurationException
1905    * if the underlying parser does
1906    */

1907   public static Transformer JavaDoc getTransformer() throws TransformerConfigurationException JavaDoc
1908   {
1909
1910      final Transformer JavaDoc trans = getTransformerFactory().newTransformer();
1911      trans.setOutputProperty(OutputKeys.INDENT, PARAM_YES);
1912
1913      return trans;
1914   }
1915
1916   /**
1917    * get a new Transformer from the TransformerFactory with the passed output properties
1918    *
1919    * @param transProps a Porperties file containing the desired Output properties
1920    * @return the new Transformer
1921    * @throws javax.xml.transform.TransformerConfigurationException
1922    * if the underlying parser does
1923    */

1924   public static Transformer JavaDoc getTransformer(final Properties JavaDoc transProps) throws TransformerConfigurationException JavaDoc
1925   {
1926
1927      final Transformer JavaDoc trans = getTransformerFactory().newTransformer();
1928
1929      if (transProps != null)
1930      {
1931         trans.setOutputProperties(transProps);
1932      }
1933
1934      return trans;
1935   }
1936
1937   /**
1938    * get a new Transformer for the passed Source (the xsl) from the TransformerFactory with indent turned on
1939    *
1940    * @param strSource a Source (StreamSource, DOMSource, SAXSource) representing the style we need the Transformer for
1941    * @return the new Transformer
1942    * @throws javax.xml.transform.TransformerConfigurationException
1943    * if the underlying parser does
1944    */

1945   public static Transformer JavaDoc getTransformer(final Source JavaDoc strSource) throws TransformerConfigurationException JavaDoc
1946   {
1947
1948      return getTransformer(getTemplates(strSource));
1949   }
1950
1951   /**
1952    * get a new Transformer for the passed compiled xsl template (with indent turned on)
1953    *
1954    * @param templates the pre compile xsl style sheet
1955    * @return the new Transformer
1956    * @throws javax.xml.transform.TransformerConfigurationException
1957    * if the underlying parser does
1958    */

1959   public static Transformer JavaDoc getTransformer(final Templates JavaDoc templates) throws TransformerConfigurationException JavaDoc
1960   {
1961      return templates.newTransformer();
1962   }
1963
1964   /**
1965    * get a new Transformer for the passed Document (the xsl) from the TransformerFactory with indent turned on
1966    *
1967    * @param doc a document representing the style we need the Transformer for
1968    * @return the new Transformer (compiled xsl style sheet)
1969    * @throws javax.xml.transform.TransformerException
1970    * if the underlying parser does
1971    * @throws java.io.IOException if converting the document to a stream source fails
1972    */

1973   public static Transformer JavaDoc getTransformer(final Document JavaDoc doc) throws TransformerException JavaDoc, IOException JavaDoc
1974   {
1975
1976// //+++TODO: is there a more efficient way (DOMSource is broker unfortunately
1977
// -> doesn't allow <xsl:import ...> tags) ?
1978
final ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
1979      serialize(doc, bOut);
1980      final StreamSource JavaDoc source = new StreamSource JavaDoc(new ByteArrayInputStream JavaDoc(bOut.toByteArray()));
1981
1982// there seems to be a bug in Xalan using DOMSource and xsl:includes !!!
1983
// produces: javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException:
1984
// xsl:include is not allowed in this position in the stylesheet!
1985
// Source source = new DOMSource(doc);
1986

1987      return getTransformer(source);
1988   }
1989
1990   /**
1991    * compile the provided style sheet into templates
1992    *
1993    * @param source a StreamSource, DOMSource, ... that contains the xsl style sheet to compile
1994    * @return the compiled style sheet (where you can get the Transformer from)
1995    * @throws javax.xml.transform.TransformerConfigurationException
1996    * if the underlying parser does
1997    */

1998   public static Templates JavaDoc getTemplates(final Source JavaDoc source) throws TransformerConfigurationException JavaDoc
1999   {
2000      // Use the TransformerFactory to instantiate a Template that will work with
2001
// the stylesheet you specify. This method call also processes the stylesheet
2002
// into a compiled Templates object.
2003
return getTransformerFactory().newTemplates(source);
2004   }
2005
2006   /**
2007    * Use an XPath string to select a nodelist. XPath namespace prefixes are resolved from the contextNode.
2008    *
2009    * @param contextNode the node from which on to search in the tree
2010    * @param str the XPATH expression
2011    * @return the NodeList containing the valid nodes, or length == 0
2012    * @throws RuntimeException (possibly wrapping the original checked exception) if any exception happens
2013    * @throws javax.xml.transform.TransformerException
2014    * if the xpath expression is not valid
2015    */

2016   public static NodeList JavaDoc getSelectedNodes(final Node JavaDoc contextNode, final String JavaDoc str) throws TransformerException JavaDoc
2017   {
2018      if (contextNode == null || str == null)
2019      {
2020         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2021      }
2022      return new CachedXPathAPI().selectNodeList(contextNode, str);
2023   }
2024
2025   /**
2026    * Use an XPath string to select a single node. XPath namespace prefixes are resolved from the context node, which
2027    * may not be what you want.
2028    *
2029    * @param contextNode the node from which on to search in the tree
2030    * @param str the XPATH expression
2031    * @return The first node found that matches the XPath, or null
2032    * @throws RuntimeException (possibly wrapping the original checked exception) if any exception happens
2033    * @throws javax.xml.transform.TransformerException
2034    * if the xpath expression is not valid
2035    */

2036   public static Node JavaDoc getSelectedNode(final Node JavaDoc contextNode, final String JavaDoc str) throws TransformerException JavaDoc
2037   {
2038      if (contextNode == null || str == null)
2039      {
2040         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2041      }
2042      return getSelectedNode(new CachedXPathAPI(), contextNode, str);
2043   }
2044
2045   /**
2046    * Use an XPath string to select a single node. XPath namespace prefixes are resolved from the context node, which
2047    * may not be what you want.
2048    *
2049    * @param xpath a <code>org.apache.xpath.CachedXPathAPI</code> instance to use for xpath navigation
2050    * @param contextNode the node from which on to search in the tree
2051    * @param str the XPATH expression
2052    * @return The first node found that matches the XPath, or null
2053    * @throws RuntimeException (possibly wrapping the original checked exception) if any exception happens
2054    * @throws javax.xml.transform.TransformerException
2055    * if the xpath expression is not valid
2056    */

2057   public static Node JavaDoc getSelectedNode(final CachedXPathAPI xpath, final Node JavaDoc contextNode, final String JavaDoc str)
2058      throws TransformerException JavaDoc
2059   {
2060      if (contextNode == null || str == null)
2061      {
2062         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2063      }
2064      return xpath.selectSingleNode(contextNode, str);
2065   }
2066
2067   /**
2068    * get a TransformerFactory the factory will be cached after the first call to this method
2069    *
2070    * @return the TransformerFactory from cache
2071    */

2072   private static synchronized TransformerFactory JavaDoc getTransformerFactory()
2073   {
2074      // cache the TransformerFactory
2075
if (g_transformerFactory == null)
2076      {
2077         // Use the static TransformerFactory.newInstance() method to instantiate
2078
// a TransformerFactory. The javax.xml.transform.TransformerFactory
2079
// system property setting determines the actual class to instantiate --
2080
// org.apache.xalan.transformer.TransformerImpl.
2081

2082// // use xsltc (instead of xalan-j's default (org.apache.xalan.processor.TransformerFactoryImpl))
2083
// if (!"org.apache.xalan.xsltc.trax.TransformerFactoryImpl".equals(
2084
// System.getProperty("javax.xml.transform.TransformerFactory"))){
2085
// System.setProperty("javax.xml.transform.TransformerFactory",
2086
// "org.apache.xalan.xsltc.trax.TransformerFactoryImpl");
2087
// }
2088
g_transformerFactory = TransformerFactory.newInstance();
2089// EboURIResolver resolver = new EboURIResolver();
2090
// resolver.setParentResolver(g_transformerFactory.getURIResolver());
2091
// g_transformerFactory.setURIResolver(resolver);
2092
}
2093
2094      return g_transformerFactory;
2095   }
2096
2097   /**
2098    * get a SAXParserFactory (from cache) for the validation and name space aware properties
2099    *
2100    * @param validation if the factory should validate the document
2101    * @param nameSpaceAware if the factory should be name space aware
2102    * @return a SAXParserFactory to get a SAXParser from
2103    */

2104   public static synchronized SAXParserFactory JavaDoc getSAXParserFactory(final boolean validation,
2105                                                                   final boolean nameSpaceAware)
2106   {
2107
2108      // transform the booleans to int indexes
2109
final int validationIndex = validation ? 1 : 0;
2110      final int namespaceIndex = nameSpaceAware ? 1 : 0;
2111
2112      // if this combo is not yet in cache, then cache it now
2113
if (SAXPARSERFACTORIES[validationIndex][namespaceIndex] == null)
2114      {
2115
2116         final SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
2117         factory.setValidating(validation);
2118         factory.setNamespaceAware(nameSpaceAware);
2119
2120         SAXPARSERFACTORIES[validationIndex][namespaceIndex] = factory;
2121      }
2122
2123      return SAXPARSERFACTORIES[validationIndex][namespaceIndex];
2124   }
2125
2126   /**
2127    * parse the document from an InputStream with the provided handler
2128    *
2129    * @param in the InputStream pointing to an xml document (from file ...)
2130    * @param handler the handler to use for parsing (extends DefaultHandler)
2131    * @param validation if the parser should validate the document
2132    * @param nameSpaceAware if the parser should be name space aware
2133    * @throws javax.xml.parsers.ParserConfigurationException
2134    * if the parser is misconfigured
2135    * @throws org.xml.sax.SAXException if the parsing fails
2136    * @throws java.io.IOException if the read fails
2137    */

2138   public static void saxParse(final InputStream JavaDoc in,
2139                               final DefaultHandler JavaDoc handler,
2140                               final boolean validation,
2141                               final boolean nameSpaceAware)
2142      throws ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
2143   {
2144      final SAXParser JavaDoc saxParser = getSAXParserFactory(validation, nameSpaceAware).newSAXParser();
2145      saxParser.parse(in, handler);
2146   }
2147
2148   /**
2149    * parse the document from an InputStream with the provided handler
2150    *
2151    * @param source the InputSource to parse
2152    * @param handler the handler to use for parsing (extends DefaultHandler)
2153    * @param validation if the parser should validate the document
2154    * @param nameSpaceAware if the parser should be name space aware
2155    * @throws javax.xml.parsers.ParserConfigurationException
2156    * if the parser is misconfigured
2157    * @throws org.xml.sax.SAXException if the parsing fails
2158    * @throws java.io.IOException if the read fails
2159    */

2160   public static void saxParse(final InputSource JavaDoc source,
2161                               final DefaultHandler JavaDoc handler,
2162                               final boolean validation,
2163                               final boolean nameSpaceAware)
2164      throws ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
2165   {
2166      final SAXParser JavaDoc saxParser = getSAXParserFactory(validation, nameSpaceAware).newSAXParser();
2167      saxParser.parse(source, handler);
2168   }
2169
2170   /**
2171    * Returns the value of the first occurence of the child element specified for the node specified
2172    *
2173    * @param node the node from where on to search for a node with the name specified by #element
2174    * @param element the name of the node to look for
2175    * @return the value of the first child node of #node whose name matches #element, or null if the node can't be
2176    * found
2177    * @throws IllegalArgumentException if any of the arguments is null
2178    */

2179   public static String JavaDoc getFirstElementValue(final Node JavaDoc node, final String JavaDoc element)
2180   {
2181
2182      if (node == null || element == null)
2183      {
2184         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2185      }
2186
2187      final NodeList JavaDoc nodeList = node.getChildNodes();
2188      for (int i = 0; i < nodeList.getLength(); i++)
2189      {
2190         if (nodeList.item(i).getNodeName().equals(element))
2191         {
2192            return getElementValue(nodeList.item(i));
2193         }
2194      }
2195
2196      return null;
2197   }
2198
2199   /**
2200    * entities are often considered serperate text nodes. for example Jim&apos;s wagon is represented by three text
2201    * nodes "Jim", "&apos;", and "s wagon" Thus all children need to be concatenated in order to retrieve the proper
2202    * text node value
2203    *
2204    * @param node the node that will be inspected for children
2205    * @return the concatenated String of child element values, or an empty String (not null!)
2206    * @throws IllegalArgumentException if the provided node is null
2207    */

2208   public static String JavaDoc getElementValue(final Node JavaDoc node)
2209   {
2210
2211      if (node == null)
2212      {
2213         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2214      }
2215
2216      final StringBuffer JavaDoc nodeValue = new StringBuffer JavaDoc();
2217
2218      if (node.hasChildNodes())
2219      {
2220         Node JavaDoc curNode = node.getFirstChild();
2221         while (curNode != null)
2222         {
2223            if (curNode.getNodeValue() != null)
2224            {
2225               nodeValue.append(curNode.getNodeValue());
2226            }
2227            curNode = curNode.getNextSibling();
2228         }
2229      }
2230
2231      return nodeValue.toString();
2232   }
2233
2234   /**
2235    * Copies all of the attributes from the src Element to the dest Element.
2236    *
2237    * @param src The Element from which all attributes will be copied.
2238    * @param dest The Element to recieve the attributes in the src element.
2239    * @throws IllegalArgumentException if the provided elements are null
2240    */

2241   public static void copyAttributes(final Element JavaDoc src, final Element JavaDoc dest)
2242   {
2243
2244      if (src == null || dest == null)
2245      {
2246         throw new IllegalArgumentException JavaDoc((ERR_NO_NULL_ARGS_ALLOWED));
2247      }
2248
2249      final NamedNodeMap JavaDoc attrs = src.getAttributes();
2250      for (int i = 0; i < attrs.getLength(); i++)
2251      {
2252         final Attr JavaDoc attr = (Attr JavaDoc)attrs.item(i);
2253         dest.setAttribute(attr.getName(), attr.getValue());
2254      }
2255   }
2256}
2257
Popular Tags