KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > xml > dom > DOMUtil


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.xml.dom;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Reader JavaDoc;
20 import java.io.StringReader JavaDoc;
21 import java.io.StringWriter JavaDoc;
22 import java.io.Writer JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import javax.xml.parsers.DocumentBuilder JavaDoc;
29 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
30 import javax.xml.parsers.ParserConfigurationException JavaDoc;
31 import javax.xml.transform.OutputKeys JavaDoc;
32 import javax.xml.transform.TransformerException JavaDoc;
33
34 import org.apache.cocoon.ProcessingException;
35 import org.apache.cocoon.xml.IncludeXMLConsumer;
36 import org.apache.cocoon.xml.XMLUtils;
37 import org.apache.commons.lang.BooleanUtils;
38 import org.apache.commons.lang.StringUtils;
39 import org.apache.excalibur.source.SourceParameters;
40 import org.apache.excalibur.xml.sax.SAXParser;
41 import org.apache.excalibur.xml.sax.XMLizable;
42 import org.apache.excalibur.xml.xpath.NodeListImpl;
43 import org.apache.excalibur.xml.xpath.XPathProcessor;
44 import org.apache.excalibur.xml.xpath.XPathUtil;
45 import org.apache.xpath.XPathAPI;
46 import org.w3c.dom.DOMException JavaDoc;
47 import org.w3c.dom.Document JavaDoc;
48 import org.w3c.dom.DocumentFragment JavaDoc;
49 import org.w3c.dom.Element JavaDoc;
50 import org.w3c.dom.NamedNodeMap JavaDoc;
51 import org.w3c.dom.Node JavaDoc;
52 import org.w3c.dom.NodeList JavaDoc;
53 import org.xml.sax.InputSource JavaDoc;
54 import org.xml.sax.SAXException JavaDoc;
55 import org.xml.sax.helpers.AttributesImpl JavaDoc;
56
57 /**
58  * This class is a utility class for miscellaneous DOM functions, like
59  * getting and setting values of nodes.
60  *
61  * @author <a HREF="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
62  * @version CVS $Id: DOMUtil.java 123825 2004-12-31 21:18:01Z antonio $
63 */

64 public final class DOMUtil {
65
66     /**
67      * Get the owner of the DOM document belonging to the node.
68      * This works even if the node is the document itself.
69      *
70      * @param node The node.
71      * @return The corresponding document.
72      */

73     public static Document JavaDoc getOwnerDocument(Node JavaDoc node) {
74         if (node.getNodeType() == Node.DOCUMENT_NODE) {
75             return (Document JavaDoc) node;
76         } else {
77             return node.getOwnerDocument();
78         }
79     }
80
81     /**
82      * Get the value of the node specified by the XPath.
83      * This works similar to xsl:value-of. If the node does not exist <CODE>null</CODE>
84      * is returned.
85      *
86      * @param root The node to start the search.
87      * @param path XPath search expression.
88      * @return The value of the node or <CODE>null</CODE>
89      */

90     public static String JavaDoc getValueOfNode(XPathProcessor processor, Node JavaDoc root, String JavaDoc path)
91         throws ProcessingException {
92         if (path == null) {
93             throw new ProcessingException("Not a valid XPath: " + path);
94         }
95         if (root != null) {
96             path = StringUtils.strip(path, "/");
97             Node JavaDoc node = XPathUtil.searchSingleNode(processor, root, path);
98             if (node != null) {
99                 return getValueOfNode(node);
100             }
101         }
102        return null;
103     }
104
105     /**
106      * Get the value of the node specified by the XPath.
107      * This works similar to xsl:value-of. If the node is not found
108      * the <CODE>defaultValue</CODE> is returned.
109      *
110      * @param root The node to start the search.
111      * @param path XPath search expression.
112      * @param defaultValue The default value if the node does not exist.
113      * @return The value of the node or <CODE>defaultValue</CODE>
114      */

115     public static String JavaDoc getValueOfNode(
116         XPathProcessor processor,
117         Node JavaDoc root,
118         String JavaDoc path,
119         String JavaDoc defaultValue)
120         throws ProcessingException {
121         String JavaDoc value = getValueOfNode(processor, root, path);
122         if (value == null)
123             value = defaultValue;
124
125         return value;
126     }
127
128     /**
129      * Get the boolean value of the node specified by the XPath.
130      * This works similar to xsl:value-of. If the node exists and has a value
131      * this value is converted to a boolean, e.g. "true" or "false" as value
132      * will result into the corresponding boolean values.
133      *
134      * @param root The node to start the search.
135      * @param path XPath search expression.
136      * @return The boolean value of the node.
137      * @throws ProcessingException If the node is not found.
138      */

139     public static boolean getValueOfNodeAsBoolean(XPathProcessor processor, Node JavaDoc root, String JavaDoc path)
140         throws ProcessingException {
141         String JavaDoc value = getValueOfNode(processor, root, path);
142         if (value == null) {
143             throw new ProcessingException("No such node: " + path);
144         }
145         return Boolean.valueOf(value).booleanValue();
146     }
147
148     /**
149      * Get the boolean value of the node specified by the XPath.
150      * This works similar to xsl:value-of. If the node exists and has a value
151      * this value is converted to a boolean, e.g. "true" or "false" as value
152      * will result into the corresponding boolean values.
153      * If the node does not exist, the <CODE>defaultValue</CODE> is returned.
154      *
155      * @param root The node to start the search.
156      * @param path XPath search expression.
157      * @param defaultValue Default boolean value.
158      * @return The value of the node or <CODE>defaultValue</CODE>
159      */

160     public static boolean getValueOfNodeAsBoolean(XPathProcessor processor,
161                                                   Node JavaDoc root,
162                                                   String JavaDoc path,
163                                                   boolean defaultValue)
164     throws ProcessingException {
165         String JavaDoc value = getValueOfNode(processor, root, path);
166         if (value != null) {
167             return BooleanUtils.toBoolean(value);
168         }
169         return defaultValue;
170     }
171
172     /**
173      * Get the value of the DOM node.
174      * The value of a node is the content of the first text node.
175      * If the node has no text nodes, <code>null</code> is returned.
176      */

177     public static String JavaDoc getValueOfNode(Node JavaDoc node) {
178         if (node != null) {
179             if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
180                 return node.getNodeValue();
181             } else {
182                 node.normalize();
183                 NodeList JavaDoc childs = node.getChildNodes();
184                 int i = 0;
185                 int length = childs.getLength();
186                 while (i < length) {
187                     if (childs.item(i).getNodeType() == Node.TEXT_NODE) {
188                         return childs.item(i).getNodeValue().trim();
189                     } else {
190                         i++;
191                     }
192                 }
193             }
194         }
195         return null;
196     }
197
198     /**
199      * Get the value of the node.
200      * The value of the node is the content of the first text node.
201      * If the node has no text nodes the <CODE>defaultValue</CODE> is
202      * returned.
203      */

204     public static String JavaDoc getValueOfNode(Node JavaDoc node, String JavaDoc defaultValue) {
205         return StringUtils.defaultString(getValueOfNode(node), defaultValue);
206     }
207
208     /**
209      * Set the value of the DOM node.
210      * All current children of the node are removed and a new text node
211      * with the value is appended.
212      */

213     public static void setValueOfNode(Node JavaDoc node, String JavaDoc value) {
214         if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
215             node.setNodeValue(value);
216         } else {
217             while (node.hasChildNodes() == true) {
218                 node.removeChild(node.getFirstChild());
219             }
220             node.appendChild(node.getOwnerDocument().createTextNode(value));
221         }
222     }
223
224     /** XML definition for a document */
225     private static final String JavaDoc XML_DEFINITION = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
226     private static final String JavaDoc XML_ROOT_DEFINITION = XML_DEFINITION + "<root>";
227
228     /**
229      * Get a document fragment from a <code>Reader</code>.
230      * The reader must provide valid XML, but it is allowed that the XML
231      * has more than one root node. This xml is parsed by the
232      * specified parser instance and a DOM DocumentFragment is created.
233      */

234     public static DocumentFragment JavaDoc getDocumentFragment(SAXParser parser, Reader JavaDoc stream)
235         throws ProcessingException {
236         DocumentFragment JavaDoc frag = null;
237
238         Writer JavaDoc writer;
239         Reader JavaDoc reader;
240         boolean removeRoot = true;
241
242         try {
243             // create a writer,
244
// write the root element, then the input from the
245
// reader
246
writer = new StringWriter JavaDoc();
247
248             writer.write(XML_ROOT_DEFINITION);
249             char[] cbuf = new char[16384];
250             int len;
251             do {
252                 len = stream.read(cbuf, 0, 16384);
253                 if (len != -1) {
254                     writer.write(cbuf, 0, len);
255                 }
256             } while (len != -1);
257             writer.write("</root>");
258
259             // now test if xml input start with <?xml
260
String JavaDoc xml = writer.toString();
261             String JavaDoc searchString = XML_ROOT_DEFINITION + "<?xml ";
262             if (xml.startsWith(searchString) == true) {
263                 // now remove the surrounding root element
264
xml = xml.substring(XML_ROOT_DEFINITION.length(), xml.length() - 7);
265                 removeRoot = false;
266             }
267
268             reader = new StringReader JavaDoc(xml);
269
270             InputSource JavaDoc input = new InputSource JavaDoc(reader);
271
272             DOMBuilder builder = new DOMBuilder();
273             builder.startDocument();
274             builder.startElement("", "root", "root", new AttributesImpl JavaDoc());
275
276             IncludeXMLConsumer filter = new IncludeXMLConsumer(builder, builder);
277             parser.parse(input, filter);
278
279             builder.endElement("", "root", "root");
280             builder.endDocument();
281
282             // Create Document Fragment, remove <root>
283
final Document JavaDoc doc = builder.getDocument();
284             frag = doc.createDocumentFragment();
285             final Node JavaDoc root = doc.getDocumentElement().getFirstChild();
286             root.normalize();
287             if (removeRoot == false) {
288                 root.getParentNode().removeChild(root);
289                 frag.appendChild(root);
290             } else {
291                 Node JavaDoc child;
292                 while (root.hasChildNodes() == true) {
293                     child = root.getFirstChild();
294                     root.removeChild(child);
295                     frag.appendChild(child);
296                 }
297             }
298         } catch (SAXException JavaDoc sax) {
299             throw new ProcessingException("SAXException: " + sax, sax);
300         } catch (IOException JavaDoc ioe) {
301             throw new ProcessingException("IOException: " + ioe, ioe);
302         }
303         return frag;
304     }
305
306     /**
307      * Create a parameter object from xml.
308      * The xml is flat and consists of elements which all have exactly one text node:
309      * <parone>value_one<parone>
310      * <partwo>value_two<partwo>
311      * A parameter can occur more than once with different values.
312      * If <CODE>source</CODE> is not specified a new paramter object is created
313      * otherwise the parameters are added to source.
314      */

315     public static SourceParameters createParameters(Node JavaDoc fragment, SourceParameters source) {
316         SourceParameters par = (source == null ? new SourceParameters() : source);
317         if (fragment != null) {
318             NodeList JavaDoc childs = fragment.getChildNodes();
319             if (childs != null) {
320                 Node JavaDoc current;
321                 for (int i = 0; i < childs.getLength(); i++) {
322                     current = childs.item(i);
323
324                     // only element nodes
325
if (current.getNodeType() == Node.ELEMENT_NODE) {
326                         current.normalize();
327                         NodeList JavaDoc valueChilds = current.getChildNodes();
328                         String JavaDoc key;
329                         StringBuffer JavaDoc valueBuffer;
330                         String JavaDoc value;
331
332                         key = current.getNodeName();
333                         valueBuffer = new StringBuffer JavaDoc();
334                         for (int m = 0; m < valueChilds.getLength(); m++) {
335                             current = valueChilds.item(m); // attention: current is reused here!
336
if (current.getNodeType() == Node.TEXT_NODE) { // only text nodes
337
if (valueBuffer.length() > 0)
338                                     valueBuffer.append(' ');
339                                 valueBuffer.append(current.getNodeValue());
340                             }
341                         }
342                         value = valueBuffer.toString().trim();
343                         if (key != null && value != null && value.length() > 0) {
344                             par.setParameter(key, value);
345                         }
346                     }
347                 }
348             }
349         }
350         return par;
351     }
352
353     /**
354      * Create a string from a DOM document fragment.
355      * Only the top level text nodes are chained together to build the text.
356      */

357     public static String JavaDoc createText(DocumentFragment JavaDoc fragment) {
358         StringBuffer JavaDoc value = new StringBuffer JavaDoc();
359         if (fragment != null) {
360             NodeList JavaDoc childs = fragment.getChildNodes();
361             if (childs != null) {
362                 Node JavaDoc current;
363
364                 for (int i = 0; i < childs.getLength(); i++) {
365                     current = childs.item(i);
366
367                     // only text nodes
368
if (current.getNodeType() == Node.TEXT_NODE) {
369                         if (value.length() > 0)
370                             value.append(' ');
371                         value.append(current.getNodeValue());
372                     }
373                 }
374             }
375         }
376         return value.toString().trim();
377     }
378
379     /**
380      * Compare all attributes of two elements.
381      * This method returns true only if both nodes have the same number of
382      * attributes and the same attributes with equal values.
383      * Namespace definition nodes are ignored
384      */

385     public static boolean compareAttributes(Element JavaDoc first, Element JavaDoc second) {
386         NamedNodeMap JavaDoc attr1 = first.getAttributes();
387         NamedNodeMap JavaDoc attr2 = second.getAttributes();
388         String JavaDoc value;
389
390         if (attr1 == null && attr2 == null)
391             return true;
392         int attr1Len = (attr1 == null ? 0 : attr1.getLength());
393         int attr2Len = (attr2 == null ? 0 : attr2.getLength());
394         if (attr1Len > 0) {
395             int l = attr1.getLength();
396             for (int i = 0; i < l; i++) {
397                 if (attr1.item(i).getNodeName().startsWith("xmlns:") == true)
398                     attr1Len--;
399             }
400         }
401         if (attr2Len > 0) {
402             int l = attr2.getLength();
403             for (int i = 0; i < l; i++) {
404                 if (attr2.item(i).getNodeName().startsWith("xmlns:") == true)
405                     attr2Len--;
406             }
407         }
408         if (attr1Len != attr2Len)
409             return false;
410         int i, l;
411         int m, l2;
412         i = 0;
413         l = attr1.getLength();
414         l2 = attr2.getLength();
415         boolean ok = true;
416         // each attribute of first must be in second with the same value
417
while (i < l && ok == true) {
418             value = attr1.item(i).getNodeName();
419             if (value.startsWith("xmlns:") == false) {
420                 ok = false;
421                 m = 0;
422                 while (m < l2 && ok == false) {
423                     if (attr2.item(m).getNodeName().equals(value) == true) {
424                         // same name, same value?
425
ok = attr1.item(i).getNodeValue().equals(attr2.item(m).getNodeValue());
426                     }
427                     m++;
428                 }
429             }
430
431             i++;
432         }
433         return ok;
434     }
435
436     /**
437      * Implementation for <code>String</code> :
438      * outputs characters representing the value.
439      *
440      * @param parent The node getting the value
441      * @param text the value
442      */

443     public static void valueOf(Node JavaDoc parent, String JavaDoc text) throws ProcessingException {
444         if (text != null) {
445             parent.appendChild(parent.getOwnerDocument().createTextNode(text));
446         }
447     }
448
449     /**
450      * Implementation for <code>XMLizable</code> :
451      * outputs the value by calling <code>v.toSax(contentHandler)</code>.
452      *
453      * @param parent The node getting the value
454      * @param v the XML fragment
455      */

456     public static void valueOf(Node JavaDoc parent, XMLizable v) throws ProcessingException {
457         if (v != null) {
458             DOMBuilder builder = new DOMBuilder(parent);
459             try {
460                 v.toSAX(builder);
461             } catch (SAXException JavaDoc e) {
462                 throw new ProcessingException(e);
463             }
464         }
465     }
466
467     /**
468      * Implementation for <code>org.w3c.dom.Node</code> :
469      * converts the Node to a SAX event stream.
470      *
471      * @param parent The node getting the value
472      * @param v the value
473      */

474     public static void valueOf(Node JavaDoc parent, Node JavaDoc v) throws ProcessingException {
475         if (v != null) {
476             parent.appendChild(parent.getOwnerDocument().importNode(v, true));
477         }
478     }
479
480     /**
481      * Implementation for <code>java.util.Collection</code> :
482      * outputs the value by calling {@link #valueOf(Node, Object)} on each element of the
483      * collection.
484      *
485      * @param parent The node getting the value
486      * @param v the XML fragment
487      */

488     public static void valueOf(Node JavaDoc parent, Collection JavaDoc v) throws ProcessingException {
489         if (v != null) {
490             Iterator JavaDoc iterator = v.iterator();
491             while (iterator.hasNext()) {
492                 valueOf(parent, iterator.next());
493             }
494         }
495     }
496
497     /**
498      * Implementation for <code>java.util.Map</code> :
499      * For each entry an element is created with the childs key and value
500      * Outputs the value and the key by calling {@link #valueOf(Node, Object)}
501      * on each value and key of the Map.
502      *
503      * @param parent The node getting the value
504      * @param v the Map
505      */

506     public static void valueOf(Node JavaDoc parent, Map JavaDoc v) throws ProcessingException {
507         if (v != null) {
508             Node JavaDoc mapNode = parent.getOwnerDocument().createElementNS(null, "java.util.map");
509             parent.appendChild(mapNode);
510             for (Iterator JavaDoc iter = v.entrySet().iterator(); iter.hasNext(); ) {
511                 Map.Entry JavaDoc me = (Map.Entry JavaDoc)iter.next();
512                 
513                 Node JavaDoc entryNode = mapNode.getOwnerDocument().createElementNS(null, "entry");
514                 mapNode.appendChild(entryNode);
515
516                 Node JavaDoc keyNode = entryNode.getOwnerDocument().createElementNS(null, "key");
517                 entryNode.appendChild(keyNode);
518                 valueOf(keyNode, me.getKey());
519
520                 Node JavaDoc valueNode = entryNode.getOwnerDocument().createElementNS(null, "value");
521                 entryNode.appendChild(valueNode);
522                 valueOf(valueNode, me.getValue());
523             }
524         }
525     }
526
527     /**
528      * Implementation for <code>Object</code> depending on its class :
529      * <ul>
530      * <li>if it's an array, call {@link #valueOf(Node, Object)} on all its elements,</li>
531      * <li>if it's class has a specific {@link #valueOf(Node, Object)} implementation, use it,</li>
532      * <li>else, output it's string representation.</li>
533      * </ul>
534      *
535      * @param parent The node getting the value
536      * @param v the value
537      */

538     public static void valueOf(Node JavaDoc parent, Object JavaDoc v) throws ProcessingException {
539         if (v == null) {
540             return;
541         }
542
543         // Array: recurse over each element
544
if (v.getClass().isArray()) {
545             Object JavaDoc[] elements = (Object JavaDoc[]) v;
546
547             for (int i = 0; i < elements.length; i++) {
548                 valueOf(parent, elements[i]);
549             }
550             return;
551         }
552
553         // Check handled object types in case they were not typed in the XSP
554

555         // XMLizable
556
if (v instanceof XMLizable) {
557             valueOf(parent, (XMLizable) v);
558             return;
559         }
560
561         // Node
562
if (v instanceof Node JavaDoc) {
563             valueOf(parent, (Node JavaDoc) v);
564             return;
565         }
566
567         // Collection
568
if (v instanceof Collection JavaDoc) {
569             valueOf(parent, (Collection JavaDoc) v);
570             return;
571         }
572
573         // Map
574
if (v instanceof Map JavaDoc) {
575             valueOf(parent, (Map JavaDoc) v);
576             return;
577         }
578
579         // Give up: hope it's a string or has a meaningful string representation
580
valueOf(parent, String.valueOf(v));
581     }
582
583     /**
584      * Use an XPath string to select a single node. XPath namespace
585      * prefixes are resolved from the context node, which may not
586      * be what you want (see the next method).
587      *
588      * @param contextNode The node to start searching from.
589      * @param str A valid XPath string.
590      * @param processor The XPath processor to use
591      * @return The first node found that matches the XPath, or null.
592      *
593      * @throws TransformerException
594      */

595     public static Node JavaDoc getSingleNode(Node JavaDoc contextNode, String JavaDoc str,
596                                      XPathProcessor processor)
597     throws TransformerException JavaDoc {
598         String JavaDoc[] pathComponents = buildPathArray(str);
599         if (pathComponents == null) {
600             return processor.selectSingleNode(contextNode, str);
601         } else {
602             return getFirstNodeFromPath(contextNode, pathComponents, false);
603         }
604     }
605
606     /**
607      * Use an XPath string to select a single node. XPath namespace
608      * prefixes are resolved from the context node, which may not
609      * be what you want (see the next method).
610      *
611      * @param contextNode The node to start searching from.
612      * @param str A valid XPath string.
613      * @return The first node found that matches the XPath, or null.
614      *
615      * @throws TransformerException
616      * @deprecated
617      */

618     public static Node JavaDoc getSingleNode(Node JavaDoc contextNode, String JavaDoc str) throws TransformerException JavaDoc {
619         String JavaDoc[] pathComponents = buildPathArray(str);
620         if (pathComponents == null) {
621             return XPathAPI.selectSingleNode(contextNode, str);
622         } else {
623             return getFirstNodeFromPath(contextNode, pathComponents, false);
624         }
625     }
626
627     /**
628      * Return the <CODE>Node</CODE> from the DOM Node <CODE>rootNode</CODE>
629      * using the XPath expression <CODE>path</CODE>.
630      * If the node does not exist, it is created and then returned.
631      * This is a very simple method for creating new nodes. If the
632      * XPath contains selectors ([,,,]) or "*" it is of course not
633      * possible to create the new node. So if you use such XPaths
634      * the node must exist beforehand.
635      * An simple exception is if the expression contains attribute
636      * test to values (e.g. [@id = 'du' and @number = 'you'],
637      * the attributes with the given values are added. The attributes
638      * must be separated with 'and'.
639      * Another problem are namespaces: XPath requires sometimes selectors for
640      * namespaces, e.g. : /*[namespace-uri()="uri" and local-name()="name"]
641      * Creating such a node with a namespace is not possible right now as we use
642      * a very simple XPath parser which is not able to parse all kinds of selectors
643      * correctly.
644      *
645      * @param rootNode The node to start the search.
646      * @param path XPath expression for searching the node.
647      * @return The node specified by the path.
648      * @throws ProcessingException If no path is specified or the XPath engine fails.
649      * @deprecated
650      */

651     public static Node JavaDoc selectSingleNode(Node JavaDoc rootNode, String JavaDoc path) throws ProcessingException {
652         // Now we have to parse the string
653
// First test: path? rootNode?
654
if (path == null) {
655             throw new ProcessingException("XPath is required.");
656         }
657         if (rootNode == null)
658             return rootNode;
659
660         if (path.length() == 0 || path.equals("/") == true)
661             return rootNode;
662
663         // now the first "quick" test is if the node exists using the
664
// full XPathAPI
665
try {
666             Node JavaDoc testNode = getSingleNode(rootNode, path);
667             if (testNode != null)
668                 return testNode;
669         } catch (javax.xml.transform.TransformerException JavaDoc local) {
670             throw new ProcessingException(
671                 "Transforming exception during selectSingleNode with path: '"
672                     + path
673                     + "'. Exception: "
674                     + local,
675                 local);
676         }
677         // Remove leading "/" on both ends
678
path = StringUtils.strip(path, "/");
679
680         // now step through the nodes!
681
Node JavaDoc parent = rootNode;
682         int pos;
683         int posSelector;
684         do {
685             pos = path.indexOf("/"); // get next separator
686
posSelector = path.indexOf("[");
687             if (posSelector != -1 && posSelector < pos) {
688                 posSelector = path.indexOf("]");
689                 pos = path.indexOf("/", posSelector);
690             }
691
692             String JavaDoc nodeName;
693             boolean isAttribute = false;
694             if (pos != -1) { // found separator
695
nodeName = path.substring(0, pos); // string until "/"
696
path = path.substring(pos + 1); // rest of string after "/"
697
} else {
698                 nodeName = path;
699             }
700
701             // test for attribute spec
702
if (nodeName.startsWith("@") == true) {
703                 isAttribute = true;
704             }
705
706             Node JavaDoc singleNode;
707             try {
708                 singleNode = getSingleNode(parent, nodeName);
709             } catch (javax.xml.transform.TransformerException JavaDoc localException) {
710                 throw new ProcessingException(
711                     "XPathUtil.selectSingleNode: " + localException.getMessage(),
712                     localException);
713             }
714
715             // create node if necessary
716
if (singleNode == null) {
717                 Node JavaDoc newNode;
718                 // delete XPath selectors
719
int posSelect = nodeName.indexOf("[");
720                 String JavaDoc XPathExp = null;
721                 if (posSelect != -1) {
722                     XPathExp = nodeName.substring(posSelect + 1, nodeName.length() - 1);
723                     nodeName = nodeName.substring(0, posSelect);
724                 }
725                 if (isAttribute == true) {
726                     try {
727                         newNode =
728                             getOwnerDocument(rootNode).createAttributeNS(
729                                 null,
730                                 nodeName.substring(1));
731                         ((Element JavaDoc) parent).setAttributeNodeNS((org.w3c.dom.Attr JavaDoc) newNode);
732                         parent = newNode;
733                     } catch (DOMException JavaDoc local) {
734                         throw new ProcessingException(
735                             "Unable to create new DOM node: '" + nodeName + "'.",
736                             local);
737                     }
738                 } else {
739                     try {
740                         newNode = getOwnerDocument(rootNode).createElementNS(null, nodeName);
741                     } catch (DOMException JavaDoc local) {
742                         throw new ProcessingException(
743                             "Unable to create new DOM node: '" + nodeName + "'.",
744                             local);
745                     }
746                     if (XPathExp != null) {
747                         java.util.List JavaDoc attrValuePairs = new java.util.ArrayList JavaDoc(4);
748                         boolean noError = true;
749
750                         String JavaDoc attr;
751                         String JavaDoc value;
752                         // scan for attributes
753
java.util.StringTokenizer JavaDoc tokenizer =
754                             new java.util.StringTokenizer JavaDoc(XPathExp, "= ");
755                         while (tokenizer.hasMoreTokens() == true) {
756                             attr = tokenizer.nextToken();
757                             if (attr.startsWith("@") == true) {
758                                 if (tokenizer.hasMoreTokens() == true) {
759                                     value = tokenizer.nextToken();
760                                     if (value.startsWith("'") && value.endsWith("'"))
761                                         value = value.substring(1, value.length() - 1);
762                                     if (value.startsWith("\"") && value.endsWith("\""))
763                                         value = value.substring(1, value.length() - 1);
764                                     attrValuePairs.add(attr.substring(1));
765                                     attrValuePairs.add(value);
766                                 } else {
767                                     noError = false;
768                                 }
769                             } else if (attr.trim().equals("and") == false) {
770                                 noError = false;
771                             }
772                         }
773                         if (noError == true) {
774                             for (int l = 0; l < attrValuePairs.size(); l = l + 2) {
775                                 ((Element JavaDoc) newNode).setAttributeNS(
776                                     null,
777                                     (String JavaDoc) attrValuePairs.get(l),
778                                     (String JavaDoc) attrValuePairs.get(l + 1));
779                             }
780                         }
781                     }
782                     parent.appendChild(newNode);
783                     parent = newNode;
784                 }
785             } else {
786                 parent = singleNode;
787             }
788         }
789         while (pos != -1);
790         return parent;
791     }
792
793     /**
794      * Return the <CODE>Node</CODE> from the DOM Node <CODE>rootNode</CODE>
795      * using the XPath expression <CODE>path</CODE>.
796      * If the node does not exist, it is created and then returned.
797      * This is a very simple method for creating new nodes. If the
798      * XPath contains selectors ([,,,]) or "*" it is of course not
799      * possible to create the new node. So if you use such XPaths
800      * the node must exist beforehand.
801      * An simple exception is if the expression contains attribute
802      * test to values (e.g. [@id = 'du' and @number = 'you'],
803      * the attributes with the given values are added. The attributes
804      * must be separated with 'and'.
805      * Another problem are namespaces: XPath requires sometimes selectors for
806      * namespaces, e.g. : /*[namespace-uri()="uri" and local-name()="name"]
807      * Creating such a node with a namespace is not possible right now as we use
808      * a very simple XPath parser which is not able to parse all kinds of selectors
809      * correctly.
810      *
811      * @param rootNode The node to start the search.
812      * @param path XPath expression for searching the node.
813      * @param processor The XPath processor to use
814      * @return The node specified by the path.
815      * @throws ProcessingException If no path is specified or the XPath engine fails.
816      */

817     public static Node JavaDoc selectSingleNode(Node JavaDoc rootNode, String JavaDoc path, XPathProcessor processor)
818     throws ProcessingException {
819         // Now we have to parse the string
820
// First test: path? rootNode?
821
if (path == null) {
822             throw new ProcessingException("XPath is required.");
823         }
824         if (rootNode == null)
825             return rootNode;
826
827         if (path.length() == 0 || path.equals("/") == true)
828             return rootNode;
829
830         // now the first "quick" test is if the node exists using the
831
// full XPathAPI
832
try {
833             Node JavaDoc testNode = getSingleNode(rootNode, path, processor);
834             if (testNode != null)
835                 return testNode;
836         } catch (javax.xml.transform.TransformerException JavaDoc local) {
837             throw new ProcessingException(
838                 "Transforming exception during selectSingleNode with path: '"
839                     + path
840                     + "'. Exception: "
841                     + local,
842                 local);
843         }
844
845         // remove leading "/" oon both ends
846
path = StringUtils.strip(path, "/");
847
848         // now step through the nodes!
849
Node JavaDoc parent = rootNode;
850         int pos;
851         int posSelector;
852         do {
853             pos = path.indexOf("/"); // get next separator
854
posSelector = path.indexOf("[");
855             if (posSelector != -1 && posSelector < pos) {
856                 posSelector = path.indexOf("]");
857                 pos = path.indexOf("/", posSelector);
858             }
859
860             String JavaDoc nodeName;
861             boolean isAttribute = false;
862             if (pos != -1) { // found separator
863
nodeName = path.substring(0, pos); // string until "/"
864
path = path.substring(pos + 1); // rest of string after "/"
865
} else {
866                 nodeName = path;
867             }
868
869             // test for attribute spec
870
if (nodeName.startsWith("@") == true) {
871                 isAttribute = true;
872             }
873
874             Node JavaDoc singleNode;
875             try {
876                 singleNode = getSingleNode(parent, nodeName, processor);
877             } catch (javax.xml.transform.TransformerException JavaDoc localException) {
878                 throw new ProcessingException(
879                     "XPathUtil.selectSingleNode: " + localException.getMessage(),
880                     localException);
881             }
882
883             // create node if necessary
884
if (singleNode == null) {
885                 Node JavaDoc newNode;
886                 // delete XPath selectors
887
int posSelect = nodeName.indexOf("[");
888                 String JavaDoc XPathExp = null;
889                 if (posSelect != -1) {
890                     XPathExp = nodeName.substring(posSelect + 1, nodeName.length() - 1);
891                     nodeName = nodeName.substring(0, posSelect);
892                 }
893                 if (isAttribute == true) {
894                     try {
895                         newNode =
896                             getOwnerDocument(rootNode).createAttributeNS(
897                                 null,
898                                 nodeName.substring(1));
899                         ((Element JavaDoc) parent).setAttributeNodeNS((org.w3c.dom.Attr JavaDoc) newNode);
900                         parent = newNode;
901                     } catch (DOMException JavaDoc local) {
902                         throw new ProcessingException(
903                             "Unable to create new DOM node: '" + nodeName + "'.",
904                             local);
905                     }
906                 } else {
907                     try {
908                         newNode = getOwnerDocument(rootNode).createElementNS(null, nodeName);
909                     } catch (DOMException JavaDoc local) {
910                         throw new ProcessingException(
911                             "Unable to create new DOM node: '" + nodeName + "'.",
912                             local);
913                     }
914                     if (XPathExp != null) {
915                         java.util.List JavaDoc attrValuePairs = new java.util.ArrayList JavaDoc(4);
916                         boolean noError = true;
917
918                         String JavaDoc attr;
919                         String JavaDoc value;
920                         // scan for attributes
921
java.util.StringTokenizer JavaDoc tokenizer =
922                             new java.util.StringTokenizer JavaDoc(XPathExp, "= ");
923                         while (tokenizer.hasMoreTokens() == true) {
924                             attr = tokenizer.nextToken();
925                             if (attr.startsWith("@") == true) {
926                                 if (tokenizer.hasMoreTokens() == true) {
927                                     value = tokenizer.nextToken();
928                                     if (value.startsWith("'") && value.endsWith("'"))
929                                         value = value.substring(1, value.length() - 1);
930                                     if (value.startsWith("\"") && value.endsWith("\""))
931                                         value = value.substring(1, value.length() - 1);
932                                     attrValuePairs.add(attr.substring(1));
933                                     attrValuePairs.add(value);
934                                 } else {
935                                     noError = false;
936                                 }
937                             } else if (attr.trim().equals("and") == false) {
938                                 noError = false;
939                             }
940                         }
941                         if (noError == true) {
942                             for (int l = 0; l < attrValuePairs.size(); l = l + 2) {
943                                 ((Element JavaDoc) newNode).setAttributeNS(
944                                     null,
945                                     (String JavaDoc) attrValuePairs.get(l),
946                                     (String JavaDoc) attrValuePairs.get(l + 1));
947                             }
948                         }
949                     }
950                     parent.appendChild(newNode);
951                     parent = newNode;
952                 }
953             } else {
954                 parent = singleNode;
955             }
956         }
957         while (pos != -1);
958         return parent;
959     }
960
961     /**
962      * Get the value of the node specified by the XPath.
963      * This works similar to xsl:value-of. If the node does not exist <CODE>null</CODE>
964      * is returned.
965      *
966      * @param root The node to start the search.
967      * @param path XPath search expression.
968      * @return The value of the node or <CODE>null</CODE>
969      * @deprecated
970      */

971     public static String JavaDoc getValueOf(Node JavaDoc root, String JavaDoc path) throws ProcessingException {
972         if (path == null) {
973             throw new ProcessingException("Not a valid XPath: " + path);
974         }
975         if (root == null)
976             return null;
977         path = StringUtils.strip(path, "/");
978
979         try {
980             Node JavaDoc node = getSingleNode(root, path);
981             if (node != null) {
982                 return getValueOfNode(node);
983             }
984         } catch (javax.xml.transform.TransformerException JavaDoc localException) {
985             throw new ProcessingException(
986                 "XPathUtil.selectSingleNode: " + localException.getMessage(),
987                 localException);
988         }
989         return null;
990     }
991
992     /**
993      * Get the value of the node specified by the XPath.
994      * This works similar to xsl:value-of. If the node does not exist <CODE>null</CODE>
995      * is returned.
996      *
997      * @param root The node to start the search.
998      * @param path XPath search expression.
999      * @param processor The XPath processor to use
1000     * @return The value of the node or <CODE>null</CODE>
1001     */

1002    public static String JavaDoc getValueOf(Node JavaDoc root, String JavaDoc path,
1003                                    XPathProcessor processor) throws ProcessingException {
1004        if (path == null) {
1005            throw new ProcessingException("Not a valid XPath: " + path);
1006        }
1007        if (root == null)
1008            return null;
1009        path = StringUtils.strip(path, "/");
1010
1011        try {
1012            Node JavaDoc node = getSingleNode(root, path, processor);
1013            if (node != null) {
1014                return getValueOfNode(node);
1015            }
1016        } catch (javax.xml.transform.TransformerException JavaDoc localException) {
1017            throw new ProcessingException(
1018                "XPathUtil.selectSingleNode: " + localException.getMessage(),
1019                localException);
1020        }
1021        return null;
1022    }
1023
1024    /**
1025     * Get the value of the node specified by the XPath.
1026     * This works similar to xsl:value-of. If the node is not found
1027     * the <CODE>defaultValue</CODE> is returned.
1028     *
1029     * @param root The node to start the search.
1030     * @param path XPath search expression.
1031     * @param defaultValue The default value if the node does not exist.
1032     * @return The value of the node or <CODE>defaultValue</CODE>
1033     * @deprecated
1034     */

1035    public static String JavaDoc getValueOf(Node JavaDoc root, String JavaDoc path, String JavaDoc defaultValue)
1036        throws ProcessingException {
1037        String JavaDoc value = getValueOf(root, path);
1038        if (value == null) {
1039            value = defaultValue;
1040        }
1041        return value;
1042    }
1043
1044    /**
1045     * Get the value of the node specified by the XPath.
1046     * This works similar to xsl:value-of. If the node is not found
1047     * the <CODE>defaultValue</CODE> is returned.
1048     *
1049     * @param root The node to start the search.
1050     * @param path XPath search expression.
1051     * @param defaultValue The default value if the node does not exist.
1052     * @param processor The XPath Processor
1053     * @return The value of the node or <CODE>defaultValue</CODE>
1054     */

1055    public static String JavaDoc getValueOf(Node JavaDoc root, String JavaDoc path, String JavaDoc defaultValue,
1056                                    XPathProcessor processor)
1057    throws ProcessingException {
1058        String JavaDoc value = getValueOf(root, path, processor);
1059        if (value == null) {
1060            value = defaultValue;
1061        }
1062        return value;
1063    }
1064
1065    /**
1066     * Get the boolean value of the node specified by the XPath.
1067     * This works similar to xsl:value-of. If the node exists and has a value
1068     * this value is converted to a boolean, e.g. "true" or "false" as value
1069     * will result into the corresponding boolean values.
1070     *
1071     * @param root The node to start the search.
1072     * @param path XPath search expression.
1073     * @return The boolean value of the node.
1074     * @throws ProcessingException If the node is not found.
1075     * @deprecated
1076     */

1077    public static boolean getValueAsBooleanOf(Node JavaDoc root, String JavaDoc path) throws ProcessingException {
1078        String JavaDoc value = getValueOf(root, path);
1079        if (value != null) {
1080            return Boolean.valueOf(value).booleanValue();
1081        } else {
1082            throw new ProcessingException("No such node: " + path);
1083        }
1084    }
1085
1086    /**
1087     * Get the boolean value of the node specified by the XPath.
1088     * This works similar to xsl:value-of. If the node exists and has a value
1089     * this value is converted to a boolean, e.g. "true" or "false" as value
1090     * will result into the corresponding boolean values.
1091     *
1092     * @param root The node to start the search.
1093     * @param path XPath search expression.
1094     * @param processor The XPath Processor
1095     * @return The boolean value of the node.
1096     * @throws ProcessingException If the node is not found.
1097     */

1098    public static boolean getValueAsBooleanOf(Node JavaDoc root, String JavaDoc path,
1099                                              XPathProcessor processor)
1100    throws ProcessingException {
1101        String JavaDoc value = getValueOf(root, path, processor);
1102        if (value == null) {
1103            throw new ProcessingException("No such node: " + path);
1104        }
1105        return Boolean.valueOf(value).booleanValue();
1106    }
1107
1108    /**
1109     * Get the boolean value of the node specified by the XPath.
1110     * This works similar to xsl:value-of. If the node exists and has a value
1111     * this value is converted to a boolean, e.g. "true" or "false" as value
1112     * will result into the corresponding boolean values.
1113     * If the node does not exist, the <CODE>defaultValue</CODE> is returned.
1114     *
1115     * @param root The node to start the search.
1116     * @param path XPath search expression.
1117     * @param defaultValue Default boolean value.
1118     * @return The value of the node or <CODE>defaultValue</CODE>
1119     * @deprecated
1120     */

1121    public static boolean getValueAsBooleanOf(Node JavaDoc root, String JavaDoc path, boolean defaultValue)
1122        throws ProcessingException {
1123        String JavaDoc value = getValueOf(root, path);
1124        if (value != null) {
1125            return Boolean.valueOf(value).booleanValue();
1126        }
1127        return defaultValue;
1128    }
1129
1130    /**
1131     * Get the boolean value of the node specified by the XPath.
1132     * This works similar to xsl:value-of. If the node exists and has a value
1133     * this value is converted to a boolean, e.g. "true" or "false" as value
1134     * will result into the corresponding boolean values.
1135     * If the node does not exist, the <CODE>defaultValue</CODE> is returned.
1136     *
1137     * @param root The node to start the search.
1138     * @param path XPath search expression.
1139     * @param defaultValue Default boolean value.
1140     * @param processor The XPath Processor
1141     * @return The value of the node or <CODE>defaultValue</CODE>
1142     */

1143    public static boolean getValueAsBooleanOf(Node JavaDoc root, String JavaDoc path, boolean defaultValue,
1144                                              XPathProcessor processor)
1145    throws ProcessingException {
1146        String JavaDoc value = getValueOf(root, path, processor);
1147        if (value != null) {
1148            return Boolean.valueOf(value).booleanValue();
1149        }
1150        return defaultValue;
1151    }
1152
1153    /**
1154     * Create a new empty DOM document.
1155     */

1156    public static Document JavaDoc createDocument() throws ProcessingException {
1157        try {
1158            DocumentBuilderFactory JavaDoc documentFactory = DocumentBuilderFactory.newInstance();
1159            documentFactory.setNamespaceAware(true);
1160            documentFactory.setValidating(false);
1161            DocumentBuilder JavaDoc docBuilder = documentFactory.newDocumentBuilder();
1162            return docBuilder.newDocument();
1163        } catch (ParserConfigurationException JavaDoc pce) {
1164            throw new ProcessingException("Creating document failed.", pce);
1165        }
1166    }
1167
1168    /**
1169     * Use an XPath string to select a nodelist.
1170     * XPath namespace prefixes are resolved from the contextNode.
1171     *
1172     * @param contextNode The node to start searching from.
1173     * @param str A valid XPath string.
1174     * @return A NodeIterator, should never be null.
1175     *
1176     * @throws TransformerException
1177     * @deprecated
1178     */

1179    public static NodeList JavaDoc selectNodeList(Node JavaDoc contextNode, String JavaDoc str)
1180        throws TransformerException JavaDoc {
1181        String JavaDoc[] pathComponents = buildPathArray(str);
1182        if (pathComponents != null) {
1183            return getNodeListFromPath(contextNode, pathComponents);
1184        }
1185        return XPathAPI.selectNodeList(contextNode, str);
1186    }
1187
1188    /**
1189     * Use an XPath string to select a nodelist.
1190     * XPath namespace prefixes are resolved from the contextNode.
1191     *
1192     * @param contextNode The node to start searching from.
1193     * @param str A valid XPath string.
1194     * @param processor The XPath Processor
1195     * @return A NodeIterator, should never be null.
1196     *
1197     * @throws TransformerException
1198     */

1199    public static NodeList JavaDoc selectNodeList(Node JavaDoc contextNode, String JavaDoc str, XPathProcessor processor)
1200    throws TransformerException JavaDoc {
1201        String JavaDoc[] pathComponents = buildPathArray(str);
1202        if (pathComponents != null) {
1203            return getNodeListFromPath(contextNode, pathComponents);
1204        }
1205       return processor.selectNodeList(contextNode, str);
1206    }
1207
1208    /**
1209     * Build the input for the get...FromPath methods. If the XPath
1210     * expression cannot be handled by the methods, <code>null</code>
1211     * is returned.
1212     */

1213    public static String JavaDoc[] buildPathArray(String JavaDoc xpath) {
1214        String JavaDoc[] result = null;
1215        if (xpath != null && xpath.charAt(0) != '/') {
1216            // test
1217
int components = 1;
1218            int i, l;
1219            l = xpath.length();
1220            boolean found = false;
1221            i = 0;
1222            while (i < l && found == false) {
1223                switch (xpath.charAt(i)) {
1224                    case '[' :
1225                        found = true;
1226                        break;
1227                    case '(' :
1228                        found = true;
1229                        break;
1230                    case '*' :
1231                        found = true;
1232                        break;
1233                    case '@' :
1234                        found = true;
1235                        break;
1236                    case ':' :
1237                        found = true;
1238                        break;
1239                    case '/' :
1240                        components++;
1241                    default :
1242                        i++;
1243                }
1244            }
1245            if (found == false) {
1246                result = new String JavaDoc[components];
1247                if (components == 1) {
1248                    result[components - 1] = xpath;
1249                } else {
1250                    i = 0;
1251                    int start = 0;
1252                    components = 0;
1253                    while (i < l) {
1254                        if (xpath.charAt(i) == '/') {
1255                            result[components] = xpath.substring(start, i);
1256                            start = i + 1;
1257                            components++;
1258                        }
1259                        i++;
1260                    }
1261                    result[components] = xpath.substring(start);
1262                }
1263            }
1264        }
1265        return result;
1266    }
1267
1268    /**
1269     * Use a path to select the first occurence of a node. The namespace
1270     * of a node is ignored!
1271     * @param contextNode The node starting the search.
1272     * @param path The path to search the node. The
1273     * contextNode is searched for a child named path[0],
1274     * this node is searched for a child named path[1]...
1275     * @param create If a child with the corresponding name is not found
1276     * and create is set, this node will be created.
1277    */

1278    public static Node JavaDoc getFirstNodeFromPath(
1279        Node JavaDoc contextNode,
1280        final String JavaDoc[] path,
1281        final boolean create) {
1282        if (contextNode == null || path == null || path.length == 0)
1283            return contextNode;
1284        // first test if the node exists
1285
Node JavaDoc item = getFirstNodeFromPath(contextNode, path, 0);
1286        if (item == null && create == true) {
1287            int i = 0;
1288            NodeList JavaDoc childs;
1289            boolean found;
1290            int m, l;
1291            while (contextNode != null && i < path.length) {
1292                childs = contextNode.getChildNodes();
1293                found = false;
1294                if (childs != null) {
1295                    m = 0;
1296                    l = childs.getLength();
1297                    while (found == false && m < l) {
1298                        item = childs.item(m);
1299                        if (item.getNodeType() == Node.ELEMENT_NODE
1300                            && item.getLocalName().equals(path[i]) == true) {
1301                            found = true;
1302                            contextNode = item;
1303                        }
1304                        m++;
1305                    }
1306                }
1307                if (found == false) {
1308                    Element JavaDoc e = contextNode.getOwnerDocument().createElementNS(null, path[i]);
1309                    contextNode.appendChild(e);
1310                    contextNode = e;
1311                }
1312                i++;
1313            }
1314            item = contextNode;
1315        }
1316        return item;
1317    }
1318
1319    /**
1320     * Private helper method for getFirstNodeFromPath()
1321     */

1322    private static Node JavaDoc getFirstNodeFromPath(
1323        final Node JavaDoc contextNode,
1324        final String JavaDoc[] path,
1325        final int startIndex) {
1326        int i = 0;
1327        NodeList JavaDoc childs;
1328        boolean found;
1329        int l;
1330        Node JavaDoc item = null;
1331
1332        childs = contextNode.getChildNodes();
1333        found = false;
1334        if (childs != null) {
1335            i = 0;
1336            l = childs.getLength();
1337            while (found == false && i < l) {
1338                item = childs.item(i);
1339                if (item.getNodeType() == Node.ELEMENT_NODE
1340                    && path[startIndex].equals(
1341                        item.getLocalName() != null ? item.getLocalName() : item.getNodeName())
1342                        == true) {
1343                    if (startIndex == path.length - 1) {
1344                        found = true;
1345                    } else {
1346                        item = getFirstNodeFromPath(item, path, startIndex + 1);
1347                        if (item != null)
1348                            found = true;
1349                    }
1350                }
1351                if (found == false) {
1352                    i++;
1353                }
1354            }
1355            if (found == false) {
1356                item = null;
1357            }
1358        }
1359        return item;
1360    }
1361
1362    /**
1363     * Use a path to select all occurences of a node. The namespace
1364     * of a node is ignored!
1365     * @param contextNode The node starting the search.
1366     * @param path The path to search the node. The
1367     * contextNode is searched for a child named path[0],
1368     * this node is searched for a child named path[1]...
1369     */

1370    public static NodeList JavaDoc getNodeListFromPath(Node JavaDoc contextNode, String JavaDoc[] path) {
1371        if (contextNode == null)
1372            return new NodeListImpl();
1373        if (path == null || path.length == 0) {
1374            return new NodeListImpl(new Node JavaDoc[] { contextNode });
1375        }
1376        NodeListImpl result = new NodeListImpl();
1377        try {
1378            getNodesFromPath(result, contextNode, path, 0);
1379        } catch (NullPointerException JavaDoc npe) {
1380            // this NPE is thrown because the parser is not configured
1381
// to use DOM Level 2
1382
throw new NullPointerException JavaDoc(
1383                "XMLUtil.getNodeListFromPath() did catch a NullPointerException."
1384                    + "This might be due to a missconfigured XML parser which does not use DOM Level 2."
1385                    + "Make sure that you use the XML parser shipped with Cocoon.");
1386        }
1387        return result;
1388    }
1389
1390    /**
1391     * Helper method for getNodeListFromPath()
1392     */

1393    private static void getNodesFromPath(
1394        final NodeListImpl result,
1395        final Node JavaDoc contextNode,
1396        final String JavaDoc[] path,
1397        final int startIndex) {
1398        final NodeList JavaDoc childs = contextNode.getChildNodes();
1399        int m, l;
1400        Node JavaDoc item;
1401        if (startIndex == (path.length - 1)) {
1402            if (childs != null) {
1403                m = 0;
1404                l = childs.getLength();
1405                while (m < l) {
1406                    item = childs.item(m);
1407                    if (item.getNodeType() == Node.ELEMENT_NODE) {
1408                        // Work around: org.apache.xerces.dom.ElementImpl doesn't handle getLocalName() correct
1409
if (path[startIndex]
1410                            .equals(
1411                                item.getLocalName() != null
1412                                    ? item.getLocalName()
1413                                    : item.getNodeName())
1414                            == true) {
1415                            result.addNode(item);
1416                        }
1417                    }
1418                    m++;
1419                }
1420            }
1421        } else {
1422            if (childs != null) {
1423                m = 0;
1424                l = childs.getLength();
1425                while (m < l) {
1426                    item = childs.item(m);
1427                    if (item.getNodeType() == Node.ELEMENT_NODE) {
1428                        // Work around: org.apache.xerces.dom.ElementImpl doesn't handle getLocalName() correct
1429
if (path[startIndex]
1430                            .equals(
1431                                item.getLocalName() != null
1432                                    ? item.getLocalName()
1433                                    : item.getNodeName())
1434                            == true) {
1435                            getNodesFromPath(result, item, path, startIndex + 1);
1436                        }
1437                    }
1438                    m++;
1439                }
1440            }
1441        }
1442    }
1443
1444    /**
1445     * Converts a org.w3c.dom.Node to a String. Uses {@link javax.xml.transform.Transformer}
1446     * to convert from a Node to a String.
1447     *
1448     * @param node a <code>org.w3c.dom.Node</code> value
1449     * @return String representation of the document
1450     * @deprecated Use {@link XMLUtils#serializeNodeToXML(Node)} instead.
1451     */

1452    public static String JavaDoc node2String(Node JavaDoc node) {
1453        try {
1454            return XMLUtils.serializeNodeToXML(node);
1455        } catch (ProcessingException e) {
1456            // Empty
1457
}
1458        return "";
1459    }
1460
1461    /**
1462     * Create a string representation of a org.w3c.dom.Node and any
1463     * (most) subtypes.
1464     * @param node a <code>org.w3c.dom.Node</code> value
1465     * @param pretty a <code>boolean</code> value whether to format the XML
1466     * @return a <code>String</code> value
1467     * @deprecated Please use {@link XMLUtils#serializeNode(Node, Properties)} instead.
1468     */

1469    public static String JavaDoc node2String(Node JavaDoc node, boolean pretty) {
1470        try {
1471            if (pretty) {
1472                Properties JavaDoc props = new Properties JavaDoc();
1473                props.setProperty(OutputKeys.INDENT, "yes");
1474                return XMLUtils.serializeNode(node, props);
1475            } else {
1476                return XMLUtils.serializeNodeToXML(node);
1477            }
1478        } catch (ProcessingException e) {
1479        }
1480        return "";
1481    }
1482
1483    /**
1484     * Create a string representation of a org.w3c.dom.Node and any
1485     * (most) subtypes.
1486     * @param node a <code>org.w3c.dom.Node</code> value
1487     * @return a <code>StringBuffer</code> value
1488     * @deprecated Please use {@link XMLUtils#serializeNodeToXML(Node)} instead.
1489     */

1490    public static StringBuffer JavaDoc node2StringBuffer(Node JavaDoc node) {
1491        return new StringBuffer JavaDoc(node2String(node));
1492    }
1493
1494    /**
1495     * Create a string representation of a org.w3c.dom.Node and any
1496     * (most) subtypes.
1497     * @param node a <code>org.w3c.dom.Node</code> value
1498     * @param pretty a <code>boolean</code> value whether to format the XML
1499     * @param indent a <code>String</code> value containing spaces as
1500     * initial indent, if null defaults to empty string.
1501     * @return a <code>StringBuffer</code> value
1502     * @deprecated Please use {@link XMLUtils#serializeNode(Node, Properties)} instead.
1503     */

1504    public static StringBuffer JavaDoc node2StringBuffer(Node JavaDoc node, boolean pretty, String JavaDoc indent) {
1505        return new StringBuffer JavaDoc(node2String(node, pretty));
1506    }
1507}
1508
Popular Tags