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 }