View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.commons.schema.utils;
21  
22  import org.w3c.dom.*;
23  
24  import java.lang.reflect.Method;
25  
26  /**
27   * Some useful utility methods.
28   * This class was modified in Xerces2 with a view to abstracting as
29   * much as possible away from the representation of the underlying
30   * parsed structure (i.e., the DOM).  This was done so that, if Xerces
31   * ever adopts an in-memory representation more efficient than the DOM
32   * (such as a DTM), we should easily be able to convert our schema
33   * parsing to utilize it.
34   *
35   * @version $ID DOMUtil
36   */
37  public class DOMUtil {
38  
39      private static final String DEFAULT_ENCODING = "UTF-8";
40  
41  	//
42      // Constructors
43      //
44  
45      /**
46       * This class cannot be instantiated.
47       */
48      protected DOMUtil() {
49      }
50  
51      //
52      // Public static methods
53      //
54  
55      /**
56       * Finds and returns the first child element node.
57       */
58      public static Element getFirstChildElement(Node parent) {
59  
60          // search for node
61          Node child = parent.getFirstChild();
62          while (child != null) {
63              if (child.getNodeType() == Node.ELEMENT_NODE) {
64                  return (Element) child;
65              }
66              child = child.getNextSibling();
67          }
68  
69          // not found
70          return null;
71  
72      } // getFirstChildElement(Node):Element
73  
74      /**
75       * Finds and returns the last child element node.
76       */
77      public static Element getLastChildElement(Node parent) {
78  
79          // search for node
80          Node child = parent.getLastChild();
81          while (child != null) {
82              if (child.getNodeType() == Node.ELEMENT_NODE) {
83                  return (Element) child;
84              }
85              child = child.getPreviousSibling();
86          }
87  
88          // not found
89          return null;
90  
91      } // getLastChildElement(Node):Element
92  
93  
94      /**
95       * Finds and returns the next sibling element node.
96       */
97      public static Element getNextSiblingElement(Node node) {
98  
99          // search for node
100         Node sibling = node.getNextSibling();
101         while (sibling != null) {
102             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
103                 return (Element) sibling;
104             }
105             sibling = sibling.getNextSibling();
106         }
107 
108         // not found
109         return null;
110 
111     } // getNextSiblingElement(Node):Element
112 
113     /**
114      * Finds and returns the first child node with the given name.
115      */
116     public static Element getFirstChildElement(Node parent, String elemName) {
117 
118         // search for node
119         Node child = parent.getFirstChild();
120         while (child != null) {
121             if (child.getNodeType() == Node.ELEMENT_NODE) {
122                 if (child.getNodeName().equals(elemName)) {
123                     return (Element) child;
124                 }
125             }
126             child = child.getNextSibling();
127         }
128 
129         // not found
130         return null;
131 
132     } // getFirstChildElement(Node,String):Element
133 
134     /**
135      * Finds and returns the last child node with the given name.
136      */
137     public static Element getLastChildElement(Node parent, String elemName) {
138 
139         // search for node
140         Node child = parent.getLastChild();
141         while (child != null) {
142             if (child.getNodeType() == Node.ELEMENT_NODE) {
143                 if (child.getNodeName().equals(elemName)) {
144                     return (Element) child;
145                 }
146             }
147             child = child.getPreviousSibling();
148         }
149 
150         // not found
151         return null;
152 
153     } // getLastChildElement(Node,String):Element
154 
155     /**
156      * Finds and returns the next sibling node with the given name.
157      */
158     public static Element getNextSiblingElement(Node node, String elemName) {
159 
160         // search for node
161         Node sibling = node.getNextSibling();
162         while (sibling != null) {
163             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
164                 if (sibling.getNodeName().equals(elemName)) {
165                     return (Element) sibling;
166                 }
167             }
168             sibling = sibling.getNextSibling();
169         }
170 
171         // not found
172         return null;
173 
174     } // getNextSiblingdElement(Node,String):Element
175 
176     /**
177      * Finds and returns the first child node with the given qualified name.
178      */
179     public static Element getFirstChildElementNS(Node parent,
180                                                  String uri, String localpart) {
181 
182         // search for node
183         Node child = parent.getFirstChild();
184         while (child != null) {
185             if (child.getNodeType() == Node.ELEMENT_NODE) {
186                 String childURI = child.getNamespaceURI();
187                 if (childURI != null && childURI.equals(uri) &&
188                         child.getLocalName().equals(localpart)) {
189                     return (Element) child;
190                 }
191             }
192             child = child.getNextSibling();
193         }
194 
195         // not found
196         return null;
197 
198     } // getFirstChildElementNS(Node,String,String):Element
199 
200     /**
201      * Finds and returns the last child node with the given qualified name.
202      */
203     public static Element getLastChildElementNS(Node parent,
204                                                 String uri, String localpart) {
205 
206         // search for node
207         Node child = parent.getLastChild();
208         while (child != null) {
209             if (child.getNodeType() == Node.ELEMENT_NODE) {
210                 String childURI = child.getNamespaceURI();
211                 if (childURI != null && childURI.equals(uri) &&
212                         child.getLocalName().equals(localpart)) {
213                     return (Element) child;
214                 }
215             }
216             child = child.getPreviousSibling();
217         }
218 
219         // not found
220         return null;
221 
222     } // getLastChildElementNS(Node,String,String):Element
223 
224     /**
225      * Finds and returns the next sibling node with the given qualified name.
226      */
227     public static Element getNextSiblingElementNS(Node node,
228                                                   String uri, String localpart) {
229 
230         // search for node
231         Node sibling = node.getNextSibling();
232         while (sibling != null) {
233             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
234                 String siblingURI = sibling.getNamespaceURI();
235                 if (siblingURI != null && siblingURI.equals(uri) &&
236                         sibling.getLocalName().equals(localpart)) {
237                     return (Element) sibling;
238                 }
239             }
240             sibling = sibling.getNextSibling();
241         }
242 
243         // not found
244         return null;
245 
246     } // getNextSiblingdElementNS(Node,String,String):Element
247 
248     /**
249      * Finds and returns the first child node with the given name.
250      */
251     public static Element getFirstChildElement(Node parent, String elemNames[]) {
252 
253         // search for node
254         Node child = parent.getFirstChild();
255         while (child != null) {
256             if (child.getNodeType() == Node.ELEMENT_NODE) {
257                 for (int i = 0; i < elemNames.length; i++) {
258                     if (child.getNodeName().equals(elemNames[i])) {
259                         return (Element) child;
260                     }
261                 }
262             }
263             child = child.getNextSibling();
264         }
265 
266         // not found
267         return null;
268 
269     } // getFirstChildElement(Node,String[]):Element
270 
271     /**
272      * Finds and returns the last child node with the given name.
273      */
274     public static Element getLastChildElement(Node parent, String elemNames[]) {
275 
276         // search for node
277         Node child = parent.getLastChild();
278         while (child != null) {
279             if (child.getNodeType() == Node.ELEMENT_NODE) {
280                 for (int i = 0; i < elemNames.length; i++) {
281                     if (child.getNodeName().equals(elemNames[i])) {
282                         return (Element) child;
283                     }
284                 }
285             }
286             child = child.getPreviousSibling();
287         }
288 
289         // not found
290         return null;
291 
292     } // getLastChildElement(Node,String[]):Element
293 
294     /**
295      * Finds and returns the next sibling node with the given name.
296      */
297     public static Element getNextSiblingElement(Node node, String elemNames[]) {
298 
299         // search for node
300         Node sibling = node.getNextSibling();
301         while (sibling != null) {
302             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
303                 for (int i = 0; i < elemNames.length; i++) {
304                     if (sibling.getNodeName().equals(elemNames[i])) {
305                         return (Element) sibling;
306                     }
307                 }
308             }
309             sibling = sibling.getNextSibling();
310         }
311 
312         // not found
313         return null;
314 
315     } // getNextSiblingdElement(Node,String[]):Element
316 
317     /**
318      * Finds and returns the first child node with the given qualified name.
319      */
320     public static Element getFirstChildElementNS(Node parent,
321                                                  String[][] elemNames) {
322 
323         // search for node
324         Node child = parent.getFirstChild();
325         while (child != null) {
326             if (child.getNodeType() == Node.ELEMENT_NODE) {
327                 for (int i = 0; i < elemNames.length; i++) {
328                     String uri = child.getNamespaceURI();
329                     if (uri != null && uri.equals(elemNames[i][0]) &&
330                             child.getLocalName().equals(elemNames[i][1])) {
331                         return (Element) child;
332                     }
333                 }
334             }
335             child = child.getNextSibling();
336         }
337 
338         // not found
339         return null;
340 
341     } // getFirstChildElementNS(Node,String[][]):Element
342 
343     /**
344      * Finds and returns the last child node with the given qualified name.
345      */
346     public static Element getLastChildElementNS(Node parent,
347                                                 String[][] elemNames) {
348 
349         // search for node
350         Node child = parent.getLastChild();
351         while (child != null) {
352             if (child.getNodeType() == Node.ELEMENT_NODE) {
353                 for (int i = 0; i < elemNames.length; i++) {
354                     String uri = child.getNamespaceURI();
355                     if (uri != null && uri.equals(elemNames[i][0]) &&
356                             child.getLocalName().equals(elemNames[i][1])) {
357                         return (Element) child;
358                     }
359                 }
360             }
361             child = child.getPreviousSibling();
362         }
363 
364         // not found
365         return null;
366 
367     } // getLastChildElementNS(Node,String[][]):Element
368 
369     /**
370      * Finds and returns the next sibling node with the given qualified name.
371      */
372     public static Element getNextSiblingElementNS(Node node,
373                                                   String[][] elemNames) {
374 
375         // search for node
376         Node sibling = node.getNextSibling();
377         while (sibling != null) {
378             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
379                 for (int i = 0; i < elemNames.length; i++) {
380                     String uri = sibling.getNamespaceURI();
381                     if (uri != null && uri.equals(elemNames[i][0]) &&
382                             sibling.getLocalName().equals(elemNames[i][1])) {
383                         return (Element) sibling;
384                     }
385                 }
386             }
387             sibling = sibling.getNextSibling();
388         }
389 
390         // not found
391         return null;
392 
393     } // getNextSiblingdElementNS(Node,String[][]):Element
394 
395     /**
396      * Finds and returns the first child node with the given name and
397      * attribute name, value pair.
398      */
399     public static Element getFirstChildElement(Node parent,
400                                                String elemName,
401                                                String attrName,
402                                                String attrValue) {
403 
404         // search for node
405         Node child = parent.getFirstChild();
406         while (child != null) {
407             if (child.getNodeType() == Node.ELEMENT_NODE) {
408                 Element element = (Element) child;
409                 if (element.getNodeName().equals(elemName) &&
410                         element.getAttribute(attrName).equals(attrValue)) {
411                     return element;
412                 }
413             }
414             child = child.getNextSibling();
415         }
416 
417         // not found
418         return null;
419 
420     } // getFirstChildElement(Node,String,String,String):Element
421 
422     /**
423      * Finds and returns the last child node with the given name and
424      * attribute name, value pair.
425      */
426     public static Element getLastChildElement(Node parent,
427                                               String elemName,
428                                               String attrName,
429                                               String attrValue) {
430 
431         // search for node
432         Node child = parent.getLastChild();
433         while (child != null) {
434             if (child.getNodeType() == Node.ELEMENT_NODE) {
435                 Element element = (Element) child;
436                 if (element.getNodeName().equals(elemName) &&
437                         element.getAttribute(attrName).equals(attrValue)) {
438                     return element;
439                 }
440             }
441             child = child.getPreviousSibling();
442         }
443 
444         // not found
445         return null;
446 
447     } // getLastChildElement(Node,String,String,String):Element
448 
449     /**
450      * Finds and returns the next sibling node with the given name and
451      * attribute name, value pair. Since only elements have attributes,
452      * the node returned will be of type Node.ELEMENT_NODE.
453      */
454     public static Element getNextSiblingElement(Node node,
455                                                 String elemName,
456                                                 String attrName,
457                                                 String attrValue) {
458 
459         // search for node
460         Node sibling = node.getNextSibling();
461         while (sibling != null) {
462             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
463                 Element element = (Element) sibling;
464                 if (element.getNodeName().equals(elemName) &&
465                         element.getAttribute(attrName).equals(attrValue)) {
466                     return element;
467                 }
468             }
469             sibling = sibling.getNextSibling();
470         }
471 
472         // not found
473         return null;
474 
475     } // getNextSiblingElement(Node,String,String,String):Element
476 
477     /**
478      * Returns the concatenated child text of the specified node.
479      * This method only looks at the immediate children of type
480      * <code>Node.TEXT_NODE</code> or the children of any child
481      * node that is of type <code>Node.CDATA_SECTION_NODE</code>
482      * for the concatenation.
483      *
484      * @param node The node to look at.
485      */
486     public static String getChildText(Node node) {
487 
488         // is there anything to do?
489         if (node == null) {
490             return null;
491         }
492 
493         // concatenate children text
494         StringBuffer str = new StringBuffer();
495         Node child = node.getFirstChild();
496         while (child != null) {
497             short type = child.getNodeType();
498             if (type == Node.TEXT_NODE) {
499                 str.append(child.getNodeValue());
500             } else if (type == Node.CDATA_SECTION_NODE) {
501                 str.append(getChildText(child));
502             }
503             child = child.getNextSibling();
504         }
505 
506         // return text value
507         return str.toString();
508 
509     } // getChildText(Node):String
510 
511     // return the name of this element
512     public static String getName(Node node) {
513         return node.getNodeName();
514     } // getLocalName(Element):  String
515 
516     /**
517      * returns local name of this element if not null, otherwise
518      * returns the name of the node
519      */
520     public static String getLocalName(Node node) {
521         String name = node.getLocalName();
522         return (name != null) ? name : node.getNodeName();
523     } // getLocalName(Element):  String
524 
525     public static Element getParent(Element elem) {
526         Node parent = elem.getParentNode();
527         if (parent instanceof Element)
528             return (Element) parent;
529         return null;
530     } // getParent(Element):Element
531 
532     // get the Document of which this Node is a part
533     public static Document getDocument(Node node) {
534         return node.getOwnerDocument();
535     } // getDocument(Node):Document
536 
537     // return this Document's root node
538     public static Element getRoot(Document doc) {
539         return doc.getDocumentElement();
540     } // getRoot(Document(:  Element
541 
542     // some methods for handling attributes:
543 
544     // return the right attribute node
545     public static Attr getAttr(Element elem, String name) {
546         return elem.getAttributeNode(name);
547     } // getAttr(Element, String):Attr
548 
549     // return the right attribute node
550     public static Attr getAttrNS(Element elem, String nsUri,
551                                  String localName) {
552         return elem.getAttributeNodeNS(nsUri, localName);
553     } // getAttrNS(Element, String):Attr
554 
555     // get all the attributes for an Element
556     public static Attr[] getAttrs(Element elem) {
557         NamedNodeMap attrMap = elem.getAttributes();
558         Attr[] attrArray = new Attr[attrMap.getLength()];
559         for (int i = 0; i < attrMap.getLength(); i++)
560             attrArray[i] = (Attr) attrMap.item(i);
561         return attrArray;
562     } // getAttrs(Element):  Attr[]
563 
564     // get attribute's value
565     public static String getValue(Attr attribute) {
566         return attribute.getValue();
567     } // getValue(Attr):String
568 
569     // It is noteworthy that, because of the way the DOM specs
570     // work, the next two methods return the empty string (not
571     // null!) when the attribute with the specified name does not
572     // exist on an element.  Beware!
573 
574     // return the value of the attribute of the given element
575     // with the given name
576     public static String getAttrValue(Element elem, String name) {
577         return elem.getAttribute(name);
578     } // getAttr(Element, String):Attr
579 
580     // return the value of the attribute of the given element
581     // with the given name
582     public static String getAttrValueNS(Element elem, String nsUri,
583                                         String localName) {
584         return elem.getAttributeNS(nsUri, localName);
585     } // getAttrValueNS(Element, String):Attr
586 
587     // return the namespace URI
588     public static String getNamespaceURI(Node node) {
589         return node.getNamespaceURI();
590     }
591 
592     /**
593      * Get the input encoding of the document. This uses a DOM 3 API
594      * call getInputEncoding hence it returns the correct value
595      * only if a DOM3 API is used. Otherwise it returns the default encoding
596      * @param doc
597      * @return the encoding (e.g. UTF-8)
598      */
599     public static String getInputEncoding(Document doc) {
600         try {
601             Method m = doc.getClass().getMethod("getInputEncoding", new Class[]{});
602             return (String) m.invoke(doc, new Object[]{});
603         } catch (Throwable e) {
604             return DEFAULT_ENCODING;
605         }
606     }
607     
608     /**
609      * Get the xml encoding of the document. This uses a DOM 3 API
610      * call getXmlEncoding hence it returns the correct value
611      * only if a DOM3 API is used. Otherwise it returns the default encoding
612      * @see #getInputEncoding(Document)
613      * @param doc
614      * @return the encoding (e.g. utf-8).
615      */
616     public static String getXmlEncoding(Document doc) {
617         try {
618         	 Method m = doc.getClass().getMethod("getXmlEncoding", new Class[]{});
619              return (String) m.invoke(doc, new Object[]{});
620         } catch (Throwable e) {
621             return DEFAULT_ENCODING;
622         }
623     }
624 }