001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/framework/xml/XMLTools.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2006 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstr. 19
030 53115 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043
044 package org.deegree.framework.xml;
045
046 import java.io.IOException;
047 import java.io.InputStream;
048 import java.io.InputStreamReader;
049 import java.io.Reader;
050 import java.net.URI;
051 import java.net.URISyntaxException;
052 import java.util.ArrayList;
053 import java.util.Iterator;
054 import java.util.List;
055 import java.util.Map;
056
057 import javax.xml.parsers.DocumentBuilder;
058 import javax.xml.parsers.DocumentBuilderFactory;
059 import javax.xml.parsers.ParserConfigurationException;
060
061 import org.deegree.datatypes.QualifiedName;
062 import org.deegree.framework.log.ILogger;
063 import org.deegree.framework.log.LoggerFactory;
064 import org.deegree.framework.util.StringTools;
065 import org.deegree.ogcbase.CommonNamespaces;
066 import org.jaxen.JaxenException;
067 import org.jaxen.XPath;
068 import org.jaxen.dom.DOMXPath;
069 import org.w3c.dom.Attr;
070 import org.w3c.dom.CDATASection;
071 import org.w3c.dom.Comment;
072 import org.w3c.dom.Document;
073 import org.w3c.dom.Element;
074 import org.w3c.dom.NamedNodeMap;
075 import org.w3c.dom.Node;
076 import org.w3c.dom.NodeList;
077 import org.w3c.dom.Text;
078 import org.xml.sax.InputSource;
079 import org.xml.sax.SAXException;
080
081 /**
082 * XML Tools based on JAXP 1.1 for parsing documents and retrieving node values/node attributes.
083 * Furthermore this utility class provides node retrieval based on XPath expressions.
084 *
085 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
086 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
087 * @author last edited by: $Author: aschmitz $
088 *
089 * @version $Revision: 7895 $, $Date: 2007-08-03 11:34:00 +0200 (Fr, 03 Aug 2007) $
090 */
091 public final class XMLTools {
092
093 private static final ILogger LOG = LoggerFactory.getLogger( XMLTools.class );
094
095 private XMLTools() {
096 // hidden constructor to prevent instantiation
097 }
098
099 // ------------------------------------------------------------------------
100 // XPath based parsing methods
101 // ------------------------------------------------------------------------
102
103 /**
104 * @param contextNode
105 * @param xPathQuery
106 * @param nsContext
107 * @return Node
108 * @throws XMLParsingException
109 */
110 public static Node getNode( Node contextNode, String xPathQuery, NamespaceContext nsContext )
111 throws XMLParsingException {
112 Node node = null;
113 try {
114 XPath xpath = new DOMXPath( xPathQuery );
115 xpath.setNamespaceContext( nsContext );
116 node = (Node) xpath.selectSingleNode( contextNode );
117
118 if ( xPathQuery.endsWith( "text()" ) ) {
119 List<Node> nl = xpath.selectNodes( contextNode );
120 int pos = xPathQuery.lastIndexOf( "/" );
121 if ( pos > 0 ) {
122 xPathQuery = xPathQuery.substring( 0, pos );
123 } else {
124 xPathQuery = ".";
125 }
126 xpath = new DOMXPath( xPathQuery );
127 xpath.setNamespaceContext( nsContext );
128 List<Node> nl_ = xpath.selectNodes( contextNode );
129 List<String> tmp = new ArrayList<String>( nl_.size() );
130 for ( int i = 0; i < nl_.size(); i++ ) {
131 tmp.add( getStringValue( nl_.get( i ) ) );
132 }
133
134 for ( int i = 0; i < nl.size(); i++ ) {
135 try {
136 nl.get( i ).getParentNode().removeChild( nl.get( i ) );
137 } catch ( Exception e ) {
138 // no exception thrown, why catch them?
139 }
140 }
141
142 Document doc = contextNode.getOwnerDocument();
143 for ( int i = 0; i < tmp.size(); i++ ) {
144 Text text = doc.createTextNode( tmp.get( i ) );
145 nl_.get( i ).appendChild( text );
146 node = text;
147 }
148 }
149
150 } catch ( JaxenException e ) {
151 throw new XMLParsingException( "Error evaluating XPath-expression '" + xPathQuery + "' from context node '"
152 + contextNode.getNodeName() + "': " + e.getMessage() );
153 }
154 return node;
155 }
156
157 /**
158 * @param contextNode
159 * @param xpath
160 * @param nsContext
161 * @return the element
162 * @throws XMLParsingException
163 * @throws ClassCastException
164 * if the node was not an element
165 */
166 public static Element getElement( Node contextNode, String xpath, NamespaceContext nsContext )
167 throws XMLParsingException {
168 Node node = getNode( contextNode, xpath, nsContext );
169 return (Element) node;
170 }
171
172 /**
173 * @param contextNode
174 * @param xPathQuery
175 * @param nsContext
176 * @param defaultValue
177 * @return the node's String value
178 * @throws XMLParsingException
179 */
180 public static String getNodeAsString( Node contextNode, String xPathQuery, NamespaceContext nsContext,
181 String defaultValue )
182 throws XMLParsingException {
183
184 String value = defaultValue;
185 Node node = getNode( contextNode, xPathQuery, nsContext );
186
187 if ( node != null ) {
188 value = getStringValue( node );
189 }
190 return value;
191 }
192
193 /**
194 * @param contextNode
195 * @param xPathQuery
196 * @param nsContext
197 * @param defaultValue
198 * @return the node's boolean value
199 * @throws XMLParsingException
200 */
201 public static boolean getNodeAsBoolean( Node contextNode, String xPathQuery, NamespaceContext nsContext,
202 boolean defaultValue )
203 throws XMLParsingException {
204 boolean value = defaultValue;
205 Node node = getNode( contextNode, xPathQuery, nsContext );
206 if ( node != null ) {
207 String stringValue = getStringValue( node );
208
209 if ( "true".equals( stringValue ) || "yes".equals( stringValue ) || "1".equals( stringValue ) ) {
210 value = true;
211 } else if ( "false".equals( stringValue ) || "no".equals( stringValue ) || "0".equals( stringValue ) ) {
212 value = false;
213 } else {
214 throw new XMLParsingException( "XPath-expression '" + xPathQuery + " ' from context node '"
215 + contextNode.getNodeName() + "' has an invalid value ('" + stringValue
216 + "'). Valid values are: 'true', 'yes', '1' " + "'false', 'no' and '0'." );
217 }
218 }
219 return value;
220 }
221
222 /**
223 * @param contextNode
224 * @param xPathQuery
225 * @param nsContext
226 * @param defaultValue
227 * @return the node's integer value
228 * @throws XMLParsingException
229 */
230 public static int getNodeAsInt( Node contextNode, String xPathQuery, NamespaceContext nsContext, int defaultValue )
231 throws XMLParsingException {
232 int value = defaultValue;
233 Node node = getNode( contextNode, xPathQuery, nsContext );
234 if ( node != null ) {
235 String stringValue = getStringValue( node );
236 try {
237 value = Integer.parseInt( stringValue );
238 } catch ( NumberFormatException e ) {
239 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
240 + "' from context node '" + contextNode.getNodeName()
241 + "' does not denote a valid integer value." );
242 }
243 }
244 return value;
245 }
246
247 /**
248 * @param contextNode
249 * @param xPathQuery
250 * @param nsContext
251 * @param defaultValue
252 * @return the node's double value
253 * @throws XMLParsingException
254 */
255 public static double getNodeAsDouble( Node contextNode, String xPathQuery, NamespaceContext nsContext,
256 double defaultValue )
257 throws XMLParsingException {
258 double value = defaultValue;
259 Node node = getNode( contextNode, xPathQuery, nsContext );
260 if ( node != null ) {
261 String stringValue = getStringValue( node );
262 try {
263 value = Double.parseDouble( stringValue );
264 } catch ( NumberFormatException e ) {
265 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
266 + "' from context node '" + contextNode.getNodeName()
267 + "' does not denote a valid double value." );
268 }
269 }
270 return value;
271 }
272
273 /**
274 * @param contextNode
275 * @param xPathQuery
276 * @param nsContext
277 * @param defaultValue
278 * @return the node as URI
279 * @throws XMLParsingException
280 */
281 public static URI getNodeAsURI( Node contextNode, String xPathQuery, NamespaceContext nsContext, URI defaultValue )
282 throws XMLParsingException {
283 URI value = defaultValue;
284 Node node = getNode( contextNode, xPathQuery, nsContext );
285 if ( node != null ) {
286 String stringValue = getStringValue( node );
287 try {
288 value = new URI( stringValue );
289 } catch ( URISyntaxException e ) {
290 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
291 + "' from context node '" + contextNode.getNodeName()
292 + "' does not denote a valid URI." );
293 }
294 }
295 return value;
296 }
297
298 /**
299 * @param contextNode
300 * @param xPathQuery
301 * @param nsContext
302 * @param defaultValue
303 * @return the node as qualified name
304 * @throws XMLParsingException
305 */
306 public static QualifiedName getNodeAsQualifiedName( Node contextNode, String xPathQuery,
307 NamespaceContext nsContext, QualifiedName defaultValue )
308 throws XMLParsingException {
309
310 QualifiedName value = defaultValue;
311 Node node = getNode( contextNode, xPathQuery, nsContext );
312
313 if ( node != null ) {
314 value = getQualifiedNameValue( node );
315 }
316 return value;
317
318 }
319
320 /**
321 * returns a list of nodes matching the passed XPath
322 *
323 * @param contextNode
324 * @param xPathQuery
325 * @param nsContext
326 * @return a list of nodes matching the passed XPath
327 * @throws XMLParsingException
328 */
329 public static List<Node> getNodes( Node contextNode, String xPathQuery, NamespaceContext nsContext )
330 throws XMLParsingException {
331 List<Node> nl = null;
332 try {
333 XPath xpath = new DOMXPath( xPathQuery );
334 xpath.setNamespaceContext( nsContext );
335 nl = xpath.selectNodes( contextNode );
336
337 if ( xPathQuery.endsWith( "text()" ) ) {
338
339 int pos = xPathQuery.lastIndexOf( "/" );
340 if ( pos > 0 ) {
341 xPathQuery = xPathQuery.substring( 0, pos );
342 } else {
343 xPathQuery = ".";
344 }
345 xpath = new DOMXPath( xPathQuery );
346 xpath.setNamespaceContext( nsContext );
347 List<?> nl_ = xpath.selectNodes( contextNode );
348 List<String> tmp = new ArrayList<String>( nl_.size() );
349 for ( int i = 0; i < nl_.size(); i++ ) {
350 tmp.add( getStringValue( (Node) nl_.get( i ) ) );
351 }
352
353 for ( int i = 0; i < nl.size(); i++ ) {
354 try {
355 nl.get( i ).getParentNode().removeChild( nl.get( i ) );
356 } catch ( Exception e ) {
357 // ignored, but why? Nothing is actually thrown here?
358 }
359 }
360
361 nl.clear();
362 Document doc = contextNode.getOwnerDocument();
363 for ( int i = 0; i < tmp.size(); i++ ) {
364 Text text = doc.createTextNode( tmp.get( i ) );
365 ( (Node) nl_.get( i ) ).appendChild( text );
366 nl.add( text );
367 }
368 }
369 } catch ( JaxenException e ) {
370 throw new XMLParsingException( "Error evaluating XPath-expression '" + xPathQuery + "' from context node '"
371 + contextNode.getNodeName() + "': " + e.getMessage(), e );
372 }
373 return nl;
374 }
375
376 /**
377 * @param contextNode
378 * @param xPathQuery
379 * @param nsContext
380 * @return the list of nodes as strings
381 * @throws XMLParsingException
382 */
383 public static String[] getNodesAsStrings( Node contextNode, String xPathQuery, NamespaceContext nsContext )
384 throws XMLParsingException {
385 String[] values = null;
386 List<Node> nl = getNodes( contextNode, xPathQuery, nsContext );
387 if ( nl != null ) {
388 values = new String[nl.size()];
389 for ( int i = 0; i < nl.size(); i++ ) {
390 values[i] = getStringValue( nl.get( i ) );
391 }
392 } else {
393 values = new String[0];
394 }
395 return values;
396 }
397
398 /**
399 * @param contextNode
400 * @param xPathQuery
401 * @param nsContext
402 * @return the nodes as URIs
403 * @throws XMLParsingException
404 */
405 public static URI[] getNodesAsURIs( Node contextNode, String xPathQuery, NamespaceContext nsContext )
406 throws XMLParsingException {
407 String[] values = getNodesAsStrings( contextNode, xPathQuery, nsContext );
408 URI[] uris = new URI[values.length];
409 for ( int i = 0; i < uris.length; i++ ) {
410 try {
411 uris[i] = new URI( values[i] );
412 } catch ( URISyntaxException e ) {
413 throw new XMLParsingException( "Result '" + values[i] + "' of XPath-expression '" + xPathQuery
414 + "' from context node '" + contextNode.getNodeName()
415 + "' does not denote a valid URI." );
416 }
417 }
418 return uris;
419 }
420
421 /**
422 * @param contextNode
423 * @param xPathQuery
424 * @param nsContext
425 * @return the nodes as qualified names
426 * @throws XMLParsingException
427 */
428 public static QualifiedName[] getNodesAsQualifiedNames( Node contextNode, String xPathQuery,
429 NamespaceContext nsContext )
430 throws XMLParsingException {
431
432 QualifiedName[] values = null;
433 List<Node> nl = getNodes( contextNode, xPathQuery, nsContext );
434 if ( nl != null ) {
435 values = new QualifiedName[nl.size()];
436 for ( int i = 0; i < nl.size(); i++ ) {
437 values[i] = getQualifiedNameValue( nl.get( i ) );
438 }
439 } else {
440 values = new QualifiedName[0];
441 }
442 return values;
443
444 }
445
446 /**
447 * @param contextNode
448 * @param xPathQuery
449 * @param nsContext
450 * @return the node
451 * @throws XMLParsingException
452 */
453 public static Node getRequiredNode( Node contextNode, String xPathQuery, NamespaceContext nsContext )
454 throws XMLParsingException {
455 Node node = getNode( contextNode, xPathQuery, nsContext );
456 if ( node == null ) {
457 throw new XMLParsingException( "XPath-expression '" + xPathQuery + "' from context node '"
458 + contextNode.getNodeName() + "' yields no result!" );
459 }
460 return node;
461 }
462
463 /**
464 * @param contextNode
465 * @param xpath
466 * @param nsContext
467 * @return the element
468 * @throws XMLParsingException
469 * @throws ClassCastException
470 * if the node was not an element
471 */
472 public static Element getRequiredElement( Node contextNode, String xpath, NamespaceContext nsContext )
473 throws XMLParsingException {
474 Node node = getRequiredNode( contextNode, xpath, nsContext );
475 return (Element) node;
476 }
477
478 /**
479 * @param contextNode
480 * @param xPathQuery
481 * @param nsContext
482 * @return the node as string
483 * @throws XMLParsingException
484 */
485 public static String getRequiredNodeAsString( Node contextNode, String xPathQuery, NamespaceContext nsContext )
486 throws XMLParsingException {
487 Node node = getRequiredNode( contextNode, xPathQuery, nsContext );
488 return getStringValue( node );
489 }
490
491 /**
492 * @param contextNode
493 * the parent of the requested node
494 * @param xPathQuery
495 * the node to get out of the dom
496 * @param nsContext
497 * context of the node
498 * @param validValues
499 * the values that are valid for the required node
500 * @return one of the String valid String values
501 * @throws XMLParsingException
502 * if no Node was found or the text of the Node was not present in the given valid
503 * strings.
504 */
505 public static String getRequiredNodeAsString( Node contextNode, String xPathQuery, NamespaceContext nsContext,
506 String[] validValues )
507 throws XMLParsingException {
508 String value = getRequiredNodeAsString( contextNode, xPathQuery, nsContext );
509 boolean found = false;
510 for ( int i = 0; i < validValues.length; i++ ) {
511 if ( value.equals( validValues[i] ) ) {
512 found = true;
513 break;
514 }
515 }
516 if ( !found ) {
517 StringBuffer sb = new StringBuffer( "XPath-expression '" + xPathQuery + " ' from context node '"
518 + contextNode.getNodeName()
519 + "' has an invalid value. Valid values are: " );
520 for ( int i = 0; i < validValues.length; i++ ) {
521 sb.append( "'" ).append( validValues[i] ).append( "'" );
522 if ( i != validValues.length - 1 ) {
523 sb.append( ", " );
524 } else {
525 sb.append( "." );
526 }
527 }
528 throw new XMLParsingException( sb.toString() );
529 }
530 return value;
531 }
532
533 /**
534 * Returns the parts of the targeted node value which are separated by the specified regex.
535 *
536 * @param contextNode
537 * @param xPathQuery
538 * @param nsContext
539 * @param regex
540 * @return the parts of the targeted node value which are separated by the specified regex.
541 * @throws XMLParsingException
542 */
543 public static String[] getRequiredNodeAsStrings( Node contextNode, String xPathQuery, NamespaceContext nsContext,
544 String regex )
545 throws XMLParsingException {
546 Node node = getRequiredNode( contextNode, xPathQuery, nsContext );
547 return StringTools.toArray( getStringValue( node ), regex, false );
548 }
549
550 /**
551 * @param contextNode
552 * @param xPathQuery
553 * @param nsContext
554 * @return the node as boolean
555 * @throws XMLParsingException
556 */
557 public static boolean getRequiredNodeAsBoolean( Node contextNode, String xPathQuery, NamespaceContext nsContext )
558 throws XMLParsingException {
559 boolean value = false;
560 Node node = getRequiredNode( contextNode, xPathQuery, nsContext );
561 String stringValue = getStringValue( node );
562 if ( "true".equals( stringValue ) || "yes".equals( stringValue ) ) {
563 value = true;
564 } else if ( "false".equals( stringValue ) || "no".equals( stringValue ) ) {
565 value = false;
566 } else {
567 throw new XMLParsingException( "XPath-expression '" + xPathQuery + " ' from context node '"
568 + contextNode.getNodeName() + "' has an invalid value ('" + stringValue
569 + "'). Valid values are: 'true', 'yes', 'false' and 'no'." );
570 }
571
572 return value;
573 }
574
575 /**
576 * @param contextNode
577 * @param xPathQuery
578 * @param nsContext
579 * @return the node as integer
580 * @throws XMLParsingException
581 */
582 public static int getRequiredNodeAsInt( Node contextNode, String xPathQuery, NamespaceContext nsContext )
583 throws XMLParsingException {
584
585 int value = 0;
586 String stringValue = getRequiredNodeAsString( contextNode, xPathQuery, nsContext );
587 try {
588 value = Integer.parseInt( stringValue );
589 } catch ( NumberFormatException e ) {
590 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
591 + "' from context node '" + contextNode.getNodeName()
592 + "' does not denote a valid integer value." );
593 }
594 return value;
595 }
596
597 /**
598 * @param contextNode
599 * @param xPathQuery
600 * @param nsContext
601 * @return the node as double
602 * @throws XMLParsingException
603 */
604 public static double getRequiredNodeAsDouble( Node contextNode, String xPathQuery, NamespaceContext nsContext )
605 throws XMLParsingException {
606
607 double value = 0;
608 String stringValue = getRequiredNodeAsString( contextNode, xPathQuery, nsContext );
609 try {
610 value = Double.parseDouble( stringValue );
611 } catch ( NumberFormatException e ) {
612 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
613 + "' from context node '" + contextNode.getNodeName()
614 + "' does not denote a valid double value." );
615 }
616 return value;
617 }
618
619 /**
620 * Returns the parts of the targeted node value which are separated by the specified regex. The
621 * string parts are converted to doubles.
622 *
623 * @param contextNode
624 * @param xPathQuery
625 * @param nsContext
626 * @param regex
627 * @return the parts of the targeted node value which are separated by the specified regex.
628 * @throws XMLParsingException
629 */
630 public static double[] getRequiredNodeAsDoubles( Node contextNode, String xPathQuery, NamespaceContext nsContext,
631 String regex )
632 throws XMLParsingException {
633 String[] parts = getRequiredNodeAsStrings( contextNode, xPathQuery, nsContext, regex );
634 double[] doubles = new double[parts.length];
635 for ( int i = 0; i < parts.length; i++ ) {
636 try {
637 doubles[i] = Double.parseDouble( parts[i] );
638 } catch ( NumberFormatException e ) {
639 throw new XMLParsingException( "Value '" + parts[i] + "' does not denote a valid double value." );
640 }
641 }
642 return doubles;
643 }
644
645 /**
646 * @param contextNode
647 * @param xPathQuery
648 * @param nsContext
649 * @return the node as URI
650 * @throws XMLParsingException
651 */
652 public static URI getRequiredNodeAsURI( Node contextNode, String xPathQuery, NamespaceContext nsContext )
653 throws XMLParsingException {
654
655 URI uri = null;
656 String stringValue = getRequiredNodeAsString( contextNode, xPathQuery, nsContext );
657
658 try {
659 uri = new URI( stringValue );
660 } catch ( URISyntaxException e ) {
661 throw new XMLParsingException( "Result '" + stringValue + "' of XPath-expression '" + xPathQuery
662 + "' from context node '" + contextNode.getNodeName()
663 + "' does not denote a valid URI." );
664 }
665 return uri;
666 }
667
668 /**
669 * @param contextNode
670 * @param xPathQuery
671 * @param nsContext
672 * @return the node as qualified name
673 * @throws XMLParsingException
674 */
675 public static QualifiedName getRequiredNodeAsQualifiedName( Node contextNode, String xPathQuery,
676 NamespaceContext nsContext )
677 throws XMLParsingException {
678 Node node = getRequiredNode( contextNode, xPathQuery, nsContext );
679 return getQualifiedNameValue( node );
680 }
681
682 /**
683 * @param contextNode
684 * @param xPathQuery
685 * @param nsContext
686 * @return the nodes
687 * @throws XMLParsingException
688 */
689 public static List<Node> getRequiredNodes( Node contextNode, String xPathQuery, NamespaceContext nsContext )
690 throws XMLParsingException {
691 List<Node> nl = getNodes( contextNode, xPathQuery, nsContext );
692 if ( nl.size() == 0 ) {
693 throw new XMLParsingException( "XPath-expression: '" + xPathQuery + "' from context node '"
694 + contextNode.getNodeName() + "' does not yield a result." );
695 }
696
697 return nl;
698 }
699
700 /**
701 * @param contextNode
702 * @param xpath
703 * @param nsContext
704 * @return a list of Elements
705 * @throws XMLParsingException
706 * @throws ClassCastException
707 * if the resulting nodes of the xpath are not elements
708 */
709 public static List<Element> getRequiredElements( Node contextNode, String xpath, NamespaceContext nsContext )
710 throws XMLParsingException {
711 List<Node> nodes = getRequiredNodes( contextNode, xpath, nsContext );
712
713 List<Element> list = new ArrayList<Element>( nodes.size() );
714 for ( Node n : nodes ) {
715 list.add( (Element) n );
716 }
717
718 return list;
719 }
720
721 /**
722 * @param contextNode
723 * @param xpath
724 * @param nsContext
725 * @return a list of Elements
726 * @throws XMLParsingException
727 * @throws ClassCastException
728 * if the resulting nodes of the xpath are not elements
729 */
730 public static List<Element> getElements( Node contextNode, String xpath, NamespaceContext nsContext )
731 throws XMLParsingException {
732 List<Node> nodes = getNodes( contextNode, xpath, nsContext );
733
734 List<Element> list = new ArrayList<Element>( nodes.size() );
735 for ( Node n : nodes ) {
736 list.add( (Element) n );
737 }
738
739 return list;
740 }
741
742 /**
743 * Returns the content of the nodes matching the XPathQuery as a String array. At least one node
744 * must match the query otherwise an exception will be thrown.
745 *
746 * @param contextNode
747 * @param xPathQuery
748 * @param nsContext
749 * @return the content of the nodes matching the XPathQuery as a String array.
750 * @throws XMLParsingException
751 */
752 public static String[] getRequiredNodesAsStrings( Node contextNode, String xPathQuery, NamespaceContext nsContext )
753 throws XMLParsingException {
754
755 List<Node> nl = getRequiredNodes( contextNode, xPathQuery, nsContext );
756
757 String[] values = new String[nl.size()];
758 for ( int i = 0; i < nl.size(); i++ ) {
759 values[i] = getStringValue( nl.get( i ) );
760 }
761
762 return values;
763 }
764
765 /**
766 * @param contextNode
767 * @param xPathQuery
768 * @param nsContext
769 * @return the qualified names
770 * @throws XMLParsingException
771 */
772 public static QualifiedName[] getRequiredNodesAsQualifiedNames( Node contextNode, String xPathQuery,
773 NamespaceContext nsContext )
774 throws XMLParsingException {
775
776 List<Node> nl = getRequiredNodes( contextNode, xPathQuery, nsContext );
777
778 QualifiedName[] values = new QualifiedName[nl.size()];
779 for ( int i = 0; i < nl.size(); i++ ) {
780 values[i] = getQualifiedNameValue( nl.get( i ) );
781 }
782
783 return values;
784 }
785
786 /**
787 * @param value
788 * @param validValues
789 * @throws XMLParsingException
790 */
791 public static void checkValue( String value, String[] validValues )
792 throws XMLParsingException {
793 for ( int i = 0; i < validValues.length; i++ ) {
794 if ( validValues[i].equals( value ) ) {
795 return;
796 }
797 }
798 StringBuffer sb = new StringBuffer( "Value '" ).append( value ).append( "' is invalid. Valid values are: " );
799 for ( int i = 0; i < validValues.length; i++ ) {
800 sb.append( "'" ).append( validValues[i] ).append( "'" );
801 if ( i != validValues.length - 1 ) {
802 sb.append( ", " );
803 } else {
804 sb.append( "." );
805 }
806 }
807 throw new XMLParsingException( sb.toString() );
808 }
809
810 // ------------------------------------------------------------------------
811 // Node creation methods
812 // ------------------------------------------------------------------------
813
814 /**
815 * Creates a new <code>Element</code> node from the given parameters and appends it to the
816 * also specified <code>Element</code>.
817 *
818 * @param element
819 * <code>Element</code> that the new <code>Element</code> is appended to
820 * @param namespaceURI
821 * use null for default namespace
822 * @param name
823 * qualified name
824 * @return the appended <code>Element</code> node
825 */
826 public static Element appendElement( Element element, URI namespaceURI, String name ) {
827 return appendElement( element, namespaceURI, name, null );
828 }
829
830 /**
831 * Appends a namespace binding for the specified element that binds the given prefix to the
832 * given namespace using a special attribute: xmlns:prefix=namespace
833 *
834 * @param element
835 * @param prefix
836 * @param namespace
837 */
838 public static void appendNSBinding( Element element, String prefix, URI namespace ) {
839 Attr attribute = element.getOwnerDocument().createAttributeNS( CommonNamespaces.XMLNS.toASCIIString(),
840 CommonNamespaces.XMLNS_PREFIX + ":" + prefix );
841 attribute.setNodeValue( namespace.toASCIIString() );
842 element.getAttributes().setNamedItemNS( attribute );
843 }
844
845 /**
846 * Appends the default namespace binding for the specified element.
847 *
848 * @param element
849 * @param prefix
850 * @param namespace
851 */
852 public static void appendNSDefaultBinding( Element element, URI namespace ) {
853 Attr attribute = element.getOwnerDocument().createAttributeNS( CommonNamespaces.XMLNS.toASCIIString(),
854 CommonNamespaces.XMLNS_PREFIX);
855 attribute.setNodeValue( namespace.toASCIIString() );
856 element.getAttributes().setNamedItemNS( attribute );
857 }
858
859 /**
860 * Appends the given namespace bindings to the specified element.
861 * <p>
862 * NOTE: The prebound prefix "xml" is skipped.
863 *
864 * @param element
865 * @param nsContext
866 */
867 public static void appendNSBindings( Element element, NamespaceContext nsContext ) {
868 Map<String, URI> namespaceMap = nsContext.getNamespaceMap();
869 Iterator<String> prefixIter = namespaceMap.keySet().iterator();
870 while ( prefixIter.hasNext() ) {
871 String prefix = prefixIter.next();
872 if ( !CommonNamespaces.XMLNS_PREFIX.equals( prefix ) ) {
873 URI namespace = namespaceMap.get( prefix );
874 appendNSBinding( element, prefix, namespace );
875 }
876 }
877 }
878
879 // ------------------------------------------------------------------------
880 // String value methods
881 // ------------------------------------------------------------------------
882
883 /**
884 * Returns the text contained in the specified element.
885 *
886 * @param node
887 * current element
888 * @return the textual contents of the element
889 */
890 public static String getStringValue( Node node ) {
891 NodeList children = node.getChildNodes();
892 StringBuffer sb = new StringBuffer( children.getLength() * 500 );
893 if ( node.getNodeValue() != null ) {
894 sb.append( node.getNodeValue().trim() );
895 }
896 if ( node.getNodeType() != Node.ATTRIBUTE_NODE ) {
897 for ( int i = 0; i < children.getLength(); i++ ) {
898 if ( children.item( i ).getNodeType() == Node.TEXT_NODE
899 || children.item( i ).getNodeType() == Node.CDATA_SECTION_NODE ) {
900 sb.append( children.item( i ).getNodeValue() );
901 }
902 }
903 }
904 return sb.toString();
905 }
906
907 /**
908 * Returns the text contained in the specified child element of the given element.
909 *
910 * @param name
911 * name of the child element
912 * @param namespace
913 * namespace of the child element
914 * @param node
915 * current element
916 * @param defaultValue
917 * default value if element is missing
918 * @return the textual contents of the element or the given default value, if missing
919 */
920 public static String getStringValue( String name, URI namespace, Node node, String defaultValue ) {
921
922 String value = defaultValue;
923 Element element = getChildElement( name, namespace, node );
924
925 if ( element != null ) {
926 value = getStringValue( element );
927 }
928 if ( value == null || value.equals( "" ) ) {
929 value = defaultValue;
930 }
931
932 return value;
933 }
934
935 /**
936 * Returns the text contained in the specified child element of the given element.
937 *
938 * @param name
939 * name of the child element
940 * @param namespace
941 * namespace of the child element
942 * @param node
943 * current element
944 * @return the textual contents of the element or null, if it is missing
945 * @throws XMLParsingException
946 * if the specified child element is missing
947 */
948 public static String getRequiredStringValue( String name, URI namespace, Node node )
949 throws XMLParsingException {
950 Element element = getRequiredChildElement( name, namespace, node );
951 return getStringValue( element );
952 }
953
954 /**
955 * Returns the value of the specified node attribute.
956 *
957 * @param name
958 * name of attribute
959 * @param namespaceURI
960 * namespace of attribute
961 * @param node
962 * current element
963 * @return the textual contents of the attribute
964 * @throws XMLParsingException
965 * if specified attribute is missing
966 */
967 public static String getRequiredAttrValue( String name, URI namespaceURI, Node node )
968 throws XMLParsingException {
969
970 String namespace = namespaceURI == null ? null : namespaceURI.toString();
971
972 String value = null;
973 NamedNodeMap atts = node.getAttributes();
974 if ( atts != null ) {
975 Attr attribute = null;
976 if ( namespace == null ) {
977 attribute = (Attr) atts.getNamedItem( name );
978 } else {
979 attribute = (Attr) atts.getNamedItemNS( namespace, name );
980 }
981
982 if ( attribute != null ) {
983 value = attribute.getValue();
984 }
985 }
986 if ( value == null ) {
987 throw new XMLParsingException( "Required attribute " + name + '(' + namespaceURI + ") of element "
988 + node.getNodeName() + " is missing." );
989 }
990 return value;
991 }
992
993 /**
994 * Parses the value of the submitted <code>Node</code> as a <code>QualifiedName</code>.
995 * <p>
996 * To parse the text contents of an <code>Element</code> node, the actual text node must be
997 * given, not the <code>Element</code> node itself.
998 * </p>
999 *
1000 * @param node
1001 * @return object representation of the element
1002 * @throws XMLParsingException
1003 */
1004 public static QualifiedName getQualifiedNameValue( Node node )
1005 throws XMLParsingException {
1006
1007 String name = node.getNodeValue().trim();
1008 QualifiedName qName = null;
1009 if ( name.indexOf( ':' ) > -1 ) {
1010 String[] tmp = StringTools.toArray( name, ":", false );
1011 try {
1012 qName = new QualifiedName( tmp[0], tmp[1], XMLTools.getNamespaceForPrefix( tmp[0], node ) );
1013 } catch ( URISyntaxException e ) {
1014 throw new XMLParsingException( e.getMessage(), e );
1015 }
1016 } else {
1017 qName = new QualifiedName( name );
1018 }
1019 return qName;
1020 }
1021
1022 /**
1023 * Returns the namespace URI that is bound to a given prefix at a certain node in the DOM tree.
1024 *
1025 * @param prefix
1026 * @param node
1027 * @return namespace URI that is bound to the given prefix, null otherwise
1028 * @throws URISyntaxException
1029 */
1030 public static URI getNamespaceForPrefix( String prefix, Node node )
1031 throws URISyntaxException {
1032 if ( node == null ) {
1033 return null;
1034 }
1035 if ( node.getNodeType() == Node.ELEMENT_NODE ) {
1036 NamedNodeMap nnm = node.getAttributes();
1037 if ( nnm != null ) {
1038 // LOG.logDebug( "(searching namespace for prefix (" + prefix
1039 // + "), resulted in a namedNodeMap for the currentNode: " + node.getNodeName() );
1040 for ( int i = 0; i < nnm.getLength(); i++ ) {
1041 Attr a = (Attr) nnm.item( i );
1042 // LOG.logDebug( "\t(searching namespace for prefix (" + prefix + "), resulted in an attribute: "
1043 // + a.getName() );
1044
1045 if ( a.getName().startsWith( "xmlns:" ) && a.getName().endsWith( ':' + prefix ) ) {
1046 return new URI( a.getValue() );
1047 } else if ( prefix == null && a.getName().equals( "xmlns" ) ) {
1048 return new URI( a.getValue() );
1049 }
1050 }
1051 }
1052 } else if ( node.getNodeType() == Node.ATTRIBUTE_NODE ) {
1053 return getNamespaceForPrefix( prefix, ( (Attr) node ).getOwnerElement() );
1054 }
1055 return getNamespaceForPrefix( prefix, node.getParentNode() );
1056 }
1057
1058 // ------------------------------------------------------------------------
1059 // Old code - deprecated
1060 // ------------------------------------------------------------------------
1061
1062 /**
1063 * Returns the specified child element of the given element. If there is more than one element
1064 * with that name, the first one is returned.
1065 *
1066 * @deprecated
1067 * @param name
1068 * name of the child element
1069 * @param namespaceURI
1070 * namespaceURI of the child element
1071 * @param node
1072 * current element
1073 * @return the element or null, if it is missing
1074 * @throws XMLParsingException
1075 * if the specified child element is missing
1076 * @throws XMLParsingException
1077 * @todo refactoring required
1078 */
1079 @Deprecated
1080 public static Element getRequiredChildElement( String name, URI namespaceURI, Node node )
1081 throws XMLParsingException {
1082
1083 String namespace = namespaceURI == null ? null : namespaceURI.toString();
1084
1085 NodeList nl = node.getChildNodes();
1086 Element element = null;
1087 Element childElement = null;
1088
1089 if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
1090 for ( int i = 0; i < nl.getLength(); i++ ) {
1091 if ( nl.item( i ) instanceof Element ) {
1092 element = (Element) nl.item( i );
1093 String s = element.getNamespaceURI();
1094 if ( ( s == null && namespace == null ) || ( namespace != null && namespace.equals( s ) ) ) {
1095 if ( element.getLocalName().equals( name ) ) {
1096 childElement = element;
1097 break;
1098 }
1099 }
1100 }
1101 }
1102 }
1103
1104 if ( childElement == null ) {
1105 throw new XMLParsingException( "Required child-element " + name + '(' + namespaceURI + ") of element "
1106 + node.getNodeName() + " is missing." );
1107 }
1108
1109 return childElement;
1110 }
1111
1112 /**
1113 * Returns the specified child element of the given element. If there is more than one with that
1114 * name, the first one is returned.
1115 *
1116 * @deprecated
1117 * @param name
1118 * name of the child element
1119 * @param namespaceURI
1120 * namespace of the child element
1121 * @param node
1122 * current element
1123 * @return the element or null, if it is missing
1124 * @TODO refactoring required
1125 */
1126 @Deprecated
1127 public static Element getChildElement( String name, URI namespaceURI, Node node ) {
1128
1129 String namespace = namespaceURI == null ? null : namespaceURI.toString();
1130
1131 NodeList nl = node.getChildNodes();
1132 Element element = null;
1133 Element childElement = null;
1134
1135 if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
1136 for ( int i = 0; i < nl.getLength(); i++ ) {
1137 if ( nl.item( i ) instanceof Element ) {
1138 element = (Element) nl.item( i );
1139 String s = element.getNamespaceURI();
1140 if ( ( s == null && namespace == null ) || ( namespace != null && namespace.equals( s ) ) ) {
1141 if ( element.getLocalName().equals( name ) ) {
1142 childElement = element;
1143 break;
1144 }
1145 }
1146 }
1147 }
1148 }
1149 return childElement;
1150 }
1151
1152 /**
1153 * Returns the specified child elements of the given element.
1154 *
1155 * @deprecated
1156 * @param name
1157 * name of the child elements
1158 * @param namespaceURI
1159 * namespaceURI of the child elements
1160 * @param node
1161 * current element
1162 * @return list of matching child elements
1163 */
1164 @Deprecated
1165 public static ElementList getChildElements( String name, URI namespaceURI, Node node ) {
1166
1167 String namespace = namespaceURI == null ? null : namespaceURI.toString();
1168
1169 NodeList nl = node.getChildNodes();
1170 Element element = null;
1171 ElementList elementList = new ElementList();
1172
1173 if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
1174 for ( int i = 0; i < nl.getLength(); i++ ) {
1175 if ( nl.item( i ) instanceof Element ) {
1176 element = (Element) nl.item( i );
1177
1178 String s = element.getNamespaceURI();
1179
1180 if ( ( s == null && namespace == null ) || ( namespace != null && namespace.equals( s ) ) ) {
1181 if ( element.getLocalName().equals( name ) ) {
1182 elementList.addElement( element );
1183 }
1184 }
1185 }
1186 }
1187 }
1188 return elementList;
1189 }
1190
1191 /**
1192 *
1193 * Create a new and empty DOM document.
1194 *
1195 * @return a new and empty DOM document.
1196 */
1197 public static Document create() {
1198 return getDocumentBuilder().newDocument();
1199 }
1200
1201 /**
1202 * Create a new document builder with:
1203 * <UL>
1204 * <li>namespace awareness = true
1205 * <li>whitespace ignoring = false
1206 * <li>validating = false
1207 * <li>expandind entity references = false
1208 * </UL>
1209 *
1210 * @return new document builder
1211 */
1212 public static synchronized DocumentBuilder getDocumentBuilder() {
1213 DocumentBuilder builder = null;
1214 try {
1215 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1216 factory.setNamespaceAware( true );
1217 factory.setExpandEntityReferences( false );
1218 factory.setIgnoringElementContentWhitespace( false );
1219 factory.setValidating( false );
1220 builder = factory.newDocumentBuilder();
1221 } catch ( Exception ex ) {
1222 LOG.logError( ex.getMessage(), ex );
1223 }
1224 return builder;
1225 }
1226
1227 /**
1228 * Returns the specified attribute value of the given node.
1229 *
1230 * @param node
1231 * current element
1232 * @param attrName
1233 * local name of the attribute
1234 *
1235 * @return the value of the attribute or null, if it is missing
1236 * @deprecated use
1237 * @see #getAttrValue(Node, URI, String, String) instead
1238 */
1239 @Deprecated
1240 public static String getAttrValue( Node node, String attrName ) {
1241 NamedNodeMap atts = node.getAttributes();
1242 if ( atts == null ) {
1243 return null;
1244 }
1245 Attr a = (Attr) atts.getNamedItem( attrName );
1246 if ( a != null ) {
1247 return a.getValue();
1248 }
1249 return null;
1250 }
1251
1252 /**
1253 * Returns the specified attribute value of the given node.
1254 *
1255 * @param node
1256 * current element
1257 * @param namespaceURI
1258 * namespace of the attribute
1259 * @param attrName
1260 * local name of the attribute
1261 * @param defaultVal
1262 * default value to be returned if attribute is nat available
1263 *
1264 * @return the value of the attribute or null, if it is missing
1265 */
1266 public static String getAttrValue( Node node, URI namespaceURI, String attrName, String defaultVal ) {
1267 String namespace = namespaceURI == null ? null : namespaceURI.toString();
1268 NamedNodeMap atts = node.getAttributes();
1269 if ( atts == null ) {
1270 return defaultVal;
1271 }
1272 Attr a = null;
1273 if ( namespace == null ) {
1274 a = (Attr) atts.getNamedItem( attrName );
1275 } else {
1276 a = (Attr) atts.getNamedItemNS( namespace, attrName );
1277 }
1278 if ( a != null ) {
1279 return a.getValue();
1280 }
1281 return defaultVal;
1282 }
1283
1284 /**
1285 * Parses an XML document and returns a DOM object. The underlying input stream is closed at the
1286 * end.
1287 *
1288 * @param reader
1289 * accessing the resource to parse
1290 * @return a DOM object, if en error occurs the response is <code>null</code>
1291 *
1292 * @throws IOException
1293 * @throws SAXException
1294 */
1295 public static Document parse( Reader reader )
1296 throws IOException, SAXException {
1297 javax.xml.parsers.DocumentBuilder parser = null;
1298 Document doc = null;
1299 try {
1300 DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
1301 fac.setNamespaceAware( true );
1302 fac.setValidating( false );
1303 fac.setIgnoringElementContentWhitespace( false );
1304 fac.setValidating( false );
1305 parser = fac.newDocumentBuilder();
1306 doc = parser.parse( new InputSource( reader ) );
1307 } catch ( ParserConfigurationException ex ) {
1308 throw new IOException( "Unable to initialize DocumentBuilder: " + ex.getMessage() );
1309 } catch ( Exception e ) {
1310 throw new SAXException( e.getMessage() );
1311 } finally {
1312 reader.close();
1313 }
1314 return doc;
1315 }
1316
1317 /**
1318 * Parses an XML document and returns a DOM object.
1319 *
1320 * @deprecated
1321 * @param is
1322 * accessing the resource to parse
1323 * @return a DOM object
1324 * @throws IOException
1325 * @throws SAXException
1326 */
1327 @Deprecated
1328 public static Document parse( InputStream is )
1329 throws IOException, SAXException {
1330 return parse( new InputStreamReader( is ) );
1331
1332 }
1333
1334 /**
1335 * Copies one node to another node.
1336 *
1337 * @param source
1338 * @param dest
1339 * @return the copied node
1340 */
1341 public static Node copyNode( Node source, Node dest ) {
1342 if ( source.getNodeType() == Node.TEXT_NODE ) {
1343 Text tn = dest.getOwnerDocument().createTextNode( getStringValue( source ) );
1344 return tn;
1345 }
1346 NamedNodeMap attr = source.getAttributes();
1347 if ( attr != null ) {
1348 for ( int i = 0; i < attr.getLength(); i++ ) {
1349 ( (Element) dest ).setAttribute( attr.item( i ).getNodeName(), attr.item( i ).getNodeValue() );
1350 }
1351 }
1352 NodeList list = source.getChildNodes();
1353 for ( int i = 0; i < list.getLength(); i++ ) {
1354 if ( !( list.item( i ) instanceof Text ) ) {
1355 if ( !( list.item( i ) instanceof Comment ) ) {
1356 Element en = dest.getOwnerDocument().createElementNS( list.item( i ).getNamespaceURI(),
1357 list.item( i ).getNodeName() );
1358 if ( list.item( i ).getNodeValue() != null ) {
1359 en.setNodeValue( list.item( i ).getNodeValue() );
1360 }
1361 Node n = copyNode( list.item( i ), en );
1362 dest.appendChild( n );
1363 }
1364 } else if ( ( list.item( i ) instanceof CDATASection ) ) {
1365 CDATASection cd = dest.getOwnerDocument().createCDATASection( list.item( i ).getNodeValue() );
1366 dest.appendChild( cd );
1367 } else {
1368 Text tn = dest.getOwnerDocument().createTextNode( list.item( i ).getNodeValue() );
1369 dest.appendChild( tn );
1370 }
1371 }
1372 return dest;
1373 }
1374
1375 /**
1376 * Appends a node to an element.
1377 * <p>
1378 * The node can be from the same document or a different one (it is automatically imported, if
1379 * necessary).
1380 *
1381 * @param source
1382 * @param dest
1383 * @return the element that is appended to
1384 */
1385 public static Node insertNodeInto( Node source, Node dest ) {
1386 // Document dDoc = null;
1387 // Document sDoc = source.getOwnerDocument();
1388 Node n = dest.getOwnerDocument().importNode( source, true );
1389 dest.appendChild( n );
1390 // if ( dest instanceof Document ) {
1391 // dDoc = (Document) dest;
1392 // } else {
1393 // dDoc = dest.getOwnerDocument();
1394 // }
1395 // if ( dDoc.equals( sDoc ) ) {
1396 // dest.appendChild( source );
1397 // } else {
1398 // Element element = dDoc.createElementNS( source.getNamespaceURI(), source.getNodeName() );
1399 // dest.appendChild( element );
1400 // // FIXME why not use Document.import() here? copyNode seems broken...
1401 // copyNode( source, element );
1402 // }
1403 return dest;
1404 }
1405
1406 /**
1407 * Returns the first child element of the submitted node.
1408 *
1409 * @param node
1410 * @return the first child element of the submitted node.
1411 */
1412 public static Element getFirstChildElement( Node node ) {
1413 NodeList nl = node.getChildNodes();
1414 Element element = null;
1415 if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
1416 for ( int i = 0; i < nl.getLength(); i++ ) {
1417 if ( nl.item( i ) instanceof Element ) {
1418 element = (Element) nl.item( i );
1419 break;
1420 }
1421 }
1422 }
1423 return element;
1424 }
1425
1426 /**
1427 * @deprecated Returns the first child element of the submitted node that matches the given
1428 * local name.
1429 *
1430 * @param node
1431 * @param name
1432 * @return the child element
1433 */
1434 @Deprecated
1435 public static Element getChildElement( Node node, String name ) {
1436 NodeList nl = node.getChildNodes();
1437 Element element = null;
1438 Element childElement = null;
1439 if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
1440 for ( int i = 0; i < nl.getLength(); i++ ) {
1441 if ( nl.item( i ) instanceof Element ) {
1442 element = (Element) nl.item( i );
1443
1444 if ( element.getNodeName().equals( name ) ) {
1445 childElement = element;
1446
1447 break;
1448 }
1449 }
1450 }
1451 }
1452 return childElement;
1453 }
1454
1455 /**
1456 * Returns all child elements of the given node.
1457 *
1458 * @param node
1459 * @return all child elements of the given node.
1460 */
1461 public static ElementList getChildElements( Node node ) {
1462 NodeList children = node.getChildNodes();
1463 ElementList list = new ElementList();
1464 for ( int i = 0; i < children.getLength(); i++ ) {
1465 if ( children.item( i ).getNodeType() == Node.ELEMENT_NODE ) {
1466 list.elements.add( (Element) children.item( i ) );
1467 }
1468 }
1469 return list;
1470 }
1471
1472 /**
1473 * sets the value of an existing node
1474 *
1475 * @param target
1476 * @param nodeValue
1477 */
1478 public static void setNodeValue( Element target, String nodeValue ) {
1479 NodeList nl = target.getChildNodes();
1480 for ( int i = 0; i < nl.getLength(); i++ ) {
1481 target.removeChild( nl.item( i ) );
1482 }
1483 Text text = target.getOwnerDocument().createTextNode( nodeValue );
1484 target.appendChild( text );
1485 }
1486
1487 /**
1488 * Creates a new <code>Element</code> node from the given parameters and appends it to the
1489 * also specified <code>Element</code>. Adds a text node to the newly generated
1490 * <code>Element</code> as well.
1491 *
1492 * @param element
1493 * <code>Element</code> that the new <code>Element</code> is appended to
1494 * @param namespaceURI
1495 * use null for default namespace
1496 * @param name
1497 * qualified name
1498 * @param nodeValue
1499 * value for a text node that is appended to the generated element
1500 * @return the appended <code>Element</code> node
1501 */
1502 public static Element appendElement( Element element, URI namespaceURI, String name, String nodeValue ) {
1503 String namespace = namespaceURI == null ? null : namespaceURI.toString();
1504 Element newElement = element.getOwnerDocument().createElementNS( namespace, name );
1505 if ( nodeValue != null && !nodeValue.equals( "" ) )
1506 newElement.appendChild( element.getOwnerDocument().createTextNode( nodeValue ) );
1507 element.appendChild( newElement );
1508 return newElement;
1509 }
1510 }