source: gli/trunk/src/org/greenstone/gatherer/util/XMLTools.java@ 20811

Last change on this file since 20811 was 20811, checked in by ak19, 15 years ago

showXMLParseFailureLine() now splits lines into an array which is used to display the erroneous line, rather than looping through lines based on the newline char which can break on the last line if this lacks a newline character.

  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 KB
Line 
1package org.greenstone.gatherer.util;
2
3
4import java.io.*;
5import java.net.*;
6import java.util.*;
7import org.apache.xerces.parsers.*;
8import org.apache.xml.serialize.*;
9import org.greenstone.gatherer.DebugStream;
10import org.w3c.dom.*;
11import org.xml.sax.*;
12
13import java.io.FileReader;
14import java.io.IOException;
15import java.io.StringReader;
16
17// SAX
18import org.xml.sax.XMLReader;
19import org.xml.sax.SAXException;
20import org.xml.sax.SAXParseException;
21import org.xml.sax.helpers.DefaultHandler;
22import org.xml.sax.InputSource;
23
24// JAXP
25import javax.xml.parsers.FactoryConfigurationError;
26import javax.xml.parsers.ParserConfigurationException;
27import javax.xml.parsers.SAXParser;
28import javax.xml.parsers.SAXParserFactory;
29
30/** This class is a static class containing useful XML functions */
31public class XMLTools {
32 /** extracts the text out of a node */
33 public static Node getNodeTextNode (Element param) {
34 param.normalize ();
35 Node n = param.getFirstChild ();
36 while (n!=null && n.getNodeType () !=Node.TEXT_NODE) {
37 n=n.getNextSibling ();
38 }
39 return n;
40 }
41
42 /** extracts the text out of a node */
43 public static String getNodeText (Element param) {
44 Node text_node = getNodeTextNode (param);
45 if (text_node == null) {
46 return "";
47 }
48 return text_node.getNodeValue ();
49 }
50 public static void setNodeText (Element elem, String text) {
51 Node old_text_node = getNodeTextNode (elem);
52 if (old_text_node != null) {
53 elem.removeChild (old_text_node);
54 }
55 Text t = elem.getOwnerDocument ().createTextNode (text);
56 elem.appendChild (t);
57 }
58 /** returns the (first) child element with the given name */
59 public static Node getChildByTagName (Node n, String name) {
60
61 Node child = n.getFirstChild ();
62 while (child!=null) {
63 if (child.getNodeName ().equals (name)) {
64 return child;
65 }
66 child = child.getNextSibling ();
67 }
68 return null; //not found
69 }
70
71 /** returns the (nth) child element with the given name
72 * index numbers start at 0 */
73 public static Node getChildByTagNameIndexed (Node n, String name, int index) {
74 if (index == -1) {
75 return getChildByTagName (n, name);
76 }
77 int count = 0;
78 Node child = n.getFirstChild ();
79 while (child!=null) {
80 if (child.getNodeName ().equals (name)) {
81 if (count == index) {
82 return child;
83 } else {
84 count++;
85 }
86 }
87 child = child.getNextSibling ();
88 }
89 return null; //not found
90 }
91
92 /** returns the element parent/node_name[@attribute_name='attribute_value']
93 */
94 public static Element getNamedElement (Element parent, String node_name,
95 String attribute_name,
96 String attribute_value) {
97
98 NodeList children = parent.getChildNodes ();
99 for (int i=0; i<children.getLength (); i++) {
100 Node child = children.item (i);
101 //logger.debug("getnamed elem, node nmae="+child.getNodeName());
102 if (child.getNodeName ().equals (node_name)) {
103 if (((Element)child).getAttribute (attribute_name).equals (attribute_value))
104 return (Element)child;
105 }
106 }
107 // not found
108 return null;
109 }
110 /** returns a list of elements parent/node_name[@attribute_name='attribute_value']
111 */
112 public static ArrayList getNamedElementList (Element parent, String node_name,
113 String attribute_name,
114 String attribute_value) {
115 ArrayList elements = new ArrayList ();
116 NodeList children = parent.getChildNodes ();
117 for (int i=0; i<children.getLength (); i++) {
118 //System.out.println("getNamedElementList");
119 Node child = children.item (i);
120 //logger.debug("getnamed elem, node nmae="+child.getNodeName());
121 if (child.getNodeName ().equals (node_name)) {
122 if (((Element)child).getAttribute (attribute_name).equals (attribute_value))
123 elements.add ((Element)child);
124 }
125 }
126 // not found
127 if (elements.size () == 0) {
128 elements = null;
129 }
130 return elements;
131 }
132 public static void copyAllChildren (Element to, Element from) {
133
134 Document to_doc = to.getOwnerDocument ();
135 Node child = from.getFirstChild ();
136 while (child != null) {
137 to.appendChild (to_doc.importNode (child, true));
138 child = child.getNextSibling ();
139 }
140 }
141 /** Duplicates an element */
142 public static Element duplicateElement (Document owner, Element element, boolean with_attributes) {
143 return duplicateElementNS (owner, element, null, with_attributes);
144 }
145
146 /** Duplicates an element */
147 public static Element duplicateElementNS (Document owner,
148 Element element,
149 String namespace_uri,
150 boolean with_attributes) {
151 Element duplicate;
152 if (namespace_uri == null) {
153 duplicate = owner.createElement (element.getTagName ());
154 } else {
155 duplicate = owner.createElementNS (namespace_uri, element.getTagName ());
156 }
157 // Copy element attributes
158 if (with_attributes) {
159 NamedNodeMap attributes = element.getAttributes ();
160 for (int i = 0; i < attributes.getLength (); i++) {
161 Node attribute = attributes.item (i);
162 duplicate.setAttribute (attribute.getNodeName (), attribute.getNodeValue ());
163 }
164 }
165
166 // Copy element children
167 NodeList children = element.getChildNodes ();
168 for (int i = 0; i < children.getLength (); i++) {
169 Node child = children.item (i);
170 duplicate.appendChild (owner.importNode (child, true));
171 }
172
173 return duplicate;
174 }
175
176
177 /** Remove all of the child nodes from a certain node. */
178 static final public void clear (Node node) {
179 while (node.hasChildNodes ()) {
180 node.removeChild (node.getFirstChild ());
181 }
182 }
183
184
185 static public ArrayList getChildElementsByTagName (Element parent_element, String element_name) {
186 ArrayList child_elements = new ArrayList ();
187
188 NodeList children_nodelist = parent_element.getChildNodes ();
189 for (int i = 0; i < children_nodelist.getLength (); i++) {
190 Node child_node = children_nodelist.item (i);
191 if (child_node.getNodeType () == Node.ELEMENT_NODE && child_node.getNodeName ().equals (element_name)) {
192 child_elements.add (child_node);
193 }
194 }
195
196 return child_elements;
197 }
198
199
200 static public String getElementTextValue (Element element) {
201 // Find the first text node child
202 NodeList children_nodelist = element.getChildNodes ();
203 for (int i = 0; i < children_nodelist.getLength (); i++) {
204 Node child_node = children_nodelist.item (i);
205 if (child_node.getNodeType () == Node.TEXT_NODE) {
206 return child_node.getNodeValue ();
207 }
208 }
209
210 // None found
211 return "";
212 }
213
214
215 /** Method to retrieve the value of a given node.
216 * @param element The <strong>Element</strong> whose value we wish to find.
217 * Soon to be deprecated!
218 */
219 static final public String getValue (Node element) {
220 if (element == null) {
221 return "";
222 }
223 // If we've been given a subject node first retrieve its value node.
224 if(element.getNodeName ().equals ("Subject")) {
225 element = getNodeFromNamed (element, "Value");
226 }
227 // If we've got a value node, then reconstruct the text. Remember that DOM will split text over 256 characters into several text nodes
228 if(element != null && element.hasChildNodes ()) {
229 StringBuffer text_buffer = new StringBuffer ();
230 NodeList text_nodes = element.getChildNodes ();
231 for(int i = 0; i < text_nodes.getLength (); i++) {
232 Node possible_text = text_nodes.item (i);
233 if(possible_text.getNodeName ().equals (StaticStrings.TEXT_NODE)) {
234 text_buffer.append (possible_text.getNodeValue ());
235 }
236 }
237 return text_buffer.toString ();
238 }
239 return "";
240 }
241
242
243 /** Method to retrieve from the node given, a certain child node with the specified name.
244 * @param parent The <strong>Node</strong> whose children should be searched.
245 * @param name The required nodes name as a <strong>String</strong>.
246 * @return The requested <strong>Node</strong> if it is found, <i>null</i> otherwise.
247 * Soon to be deprecated!
248 */
249 static final public Node getNodeFromNamed (Node parent, String name) {
250 Node child = null;
251 for(Node i = parent.getFirstChild (); i != null && child == null;
252 i = i.getNextSibling ()) {
253 if(i.getNodeName ().equals (name)) {
254 child = i;
255 }
256 }
257 return child;
258 }
259
260 static final public String WELLFORMED= "well-formed !";
261 static final public String NOTWELLFORMED= "not well-formed";
262 static final private String HEADER = "<?xml version='1.0' encoding='UTF-8'?><collectionConfig xmlns:gsf='http://www.greenstone.org/greenstone3/schema/ConfigFormat' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>";
263 static final private String FOOTER = "</collectionConfig>";
264
265public static String parse (String xml_str) {
266 String validation_msg = WELLFORMED;
267 xml_str = HEADER + xml_str + FOOTER;
268 try {
269 SAXParserFactory factory = SAXParserFactory.newInstance ();
270 factory.setNamespaceAware (true);
271 //factory.setValidating (true);
272 SAXParser parser = factory.newSAXParser ();
273 InputSource iSource = new InputSource ( new StringReader ( xml_str ) );
274// parser.parse (iSource, new DefaultHandler ());
275
276 org.xml.sax.XMLReader reader = parser.getXMLReader ();
277 reader.setContentHandler(new DefaultHandler());
278 reader.setErrorHandler(new DefaultHandler());
279 reader.parse(iSource);
280 } catch (FactoryConfigurationError e) {
281 validation_msg = "unable to get a document builder factory";
282 } catch (ParserConfigurationException e) {
283 validation_msg = "unable to configure parser";
284 } catch (SAXParseException e) {
285 validation_msg = NOTWELLFORMED + getLocationString(e) + e.getMessage ();
286 } catch (SAXException e) {
287 validation_msg += " Fatal error: " + e.toString ();
288 } catch (IOException e) {
289 validation_msg = "Unable to read the input, i/o error";
290 }
291
292 return validation_msg;
293 }
294//In this method, the parsed string xml_str is not wrapped by the header and footer strings.
295public static String parseDOM (String xml_str) {
296 String validation_msg = WELLFORMED;
297
298 try {
299 SAXParserFactory factory = SAXParserFactory.newInstance ();
300 factory.setNamespaceAware (true);
301 //factory.setValidating (true);
302 SAXParser parser = factory.newSAXParser ();
303 InputSource iSource = new InputSource ( new StringReader ( xml_str ) );
304// parser.parse (iSource, new DefaultHandler ());
305
306 org.xml.sax.XMLReader reader = parser.getXMLReader ();
307 reader.setContentHandler(new DefaultHandler());
308 reader.setErrorHandler(new DefaultHandler());
309 reader.parse(iSource);
310 } catch (FactoryConfigurationError e) {
311 validation_msg = "unable to get a document builder factory";
312 } catch (ParserConfigurationException e) {
313 validation_msg = "unable to configure parser";
314 } catch (SAXParseException e) {
315 validation_msg = NOTWELLFORMED + getLocationString(e) + e.getMessage ();
316 } catch (SAXException e) {
317 validation_msg += " " + e.toString ();
318 } catch (IOException e) {
319 validation_msg = "Unable to read the input, i/o error";
320 }
321
322 return validation_msg;
323 }
324
325public static String parse (File xml_file) {
326 String validation_msg = WELLFORMED;
327
328 try {
329 SAXParserFactory factory = SAXParserFactory.newInstance ();
330 factory.setNamespaceAware (true);
331 //factory.setValidating (true);
332 SAXParser parser = factory.newSAXParser ();
333 FileReader r = new FileReader(xml_file);
334 InputSource iSource = new InputSource(r);
335 XMLReader reader = parser.getXMLReader ();
336 reader.setContentHandler(new DefaultHandler());
337 reader.setErrorHandler(new DefaultHandler());
338 reader.parse(iSource);
339 } catch (FactoryConfigurationError e) {
340 validation_msg = "unable to get a document builder factory";
341 } catch (ParserConfigurationException e) {
342 validation_msg = "unable to configure parser";
343 } catch (SAXParseException e) {
344 validation_msg = NOTWELLFORMED + getLocationString(e) + e.getMessage ();
345 } catch (SAXException e) {
346 validation_msg += " Fatal error: " + e.toString ();
347 } catch (IOException e) {
348 validation_msg = "Unable to read the input, i/o error";
349 }
350
351 return validation_msg;
352 }
353 /** Returns a string of the location. */
354 private static String getLocationString(SAXParseException ex) {
355 StringBuffer str = new StringBuffer();
356
357 String systemId = ex.getSystemId();
358 if (systemId != null) {
359 int index = systemId.lastIndexOf('/');
360 if (index != -1)
361 systemId = systemId.substring(index + 1);
362 str.append(systemId);
363 }
364 str.append("(line ");
365 str.append(ex.getLineNumber()-1);
366 str.append(", column ");
367 str.append(ex.getColumnNumber());
368 str.append("): ");
369
370 return str.toString();
371
372 } // getLocationString(SAXParseException):String
373
374
375 /** Parse an XML document from a given file path */
376 static public Document parseXMLFile (String xml_file_path, boolean use_class_loader) {
377 if (use_class_loader == true) {
378 InputStream is = JarTools.getResourceAsStream ("/" + xml_file_path);
379 if (is != null) {
380 return parseXML (is);
381 }
382 }
383
384 // Try the file outside the classes directory
385 return parseXMLFile (new File (xml_file_path));
386 }
387
388
389 /** Parse an XML document from a given file */
390 static public Document parseXMLFile (File xml_file) {
391 // No file? No point trying!
392 if (xml_file.exists () == false) {
393 return null;
394 }
395
396 try {
397 return parseXML (new FileInputStream (xml_file));
398 }
399 catch (Exception exception) {
400 DebugStream.printStackTrace (exception);
401 return null;
402 }
403 }
404
405
406 /** Parse an XML document from a given input stream */
407 static public Document parseXML (InputStream xml_input_stream) {
408 Document document = null;
409
410 try {
411 InputStreamReader isr = new InputStreamReader (xml_input_stream, "UTF-8");
412 document = parseXML(isr);
413 isr.close ();
414 xml_input_stream.close ();
415 }
416 catch (Exception exception) {
417 DebugStream.printStackTrace (exception);
418 }
419
420 return document;
421 }
422
423
424 /** Parse an XML document from a given reader */
425 static public Document parseXML (Reader xml_reader) {
426 Document document = null;
427
428 // If debugging, the following will store the XML contents to be parsed,
429 // which can then be inspected upon encountering a SAXException (need to run GLI with -debug on)
430 String xmlContents = "";
431
432 try {
433 Reader reader = null;
434
435 // (1) By default, GLI will remove any contents preceeding (and invalidating)
436 // the XML and present these lines separately to the user
437 if(!DebugStream.isDebuggingEnabled()) {
438 try {
439 reader = new BufferedReader( new RemoveContentBeforeRootElementXMLReader(xml_reader) );
440 } catch ( Exception e ) {
441 System.err.println( "Exception while wrapping the reader in parseXML(Reader)" );
442 e.printStackTrace();
443 }
444 }
445
446 // (2) If we are running GLI in debug mode:
447 // In case parsing exceptions are thrown (SAX Exceptions), we want to get some
448 // idea of where things went wrong. This will print the "XML" contents to either
449 // system.out (if debugging is off) or to the DebugStream otherwise.
450 // We need to read the XML twice to know the line where things went wrong, so
451 // do the additional reading only if we're debugging
452 else {
453 StringBuffer buf = new StringBuffer();
454 char[] buffer = new char[500];
455 int numCharsRead = xml_reader.read(buffer, 0, buffer.length);
456 while(numCharsRead != -1) {
457 buf.append(buffer, 0, numCharsRead);
458 numCharsRead = xml_reader.read(buffer, 0, buffer.length);
459 }
460 xmlContents = buf.toString();
461 xml_reader.close(); // closing the old Reader
462 xml_reader = null;
463 buffer = null;
464 buf = null;
465 // we need a Reader to parse the same contents as the Reader that was just closed
466 reader = new BufferedReader(new StringReader(xmlContents));
467 //System.err.println("xmlContents:\n" + xmlContents);
468 }
469
470 // (2) The actual XML parsing
471 InputSource isc = new InputSource (reader);
472 DOMParser parser = new DOMParser ();
473 parser.setFeature ("http://xml.org/sax/features/validation", false);
474 parser.setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
475 // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster.
476 parser.setFeature ("http://apache.org/xml/features/dom/defer-node-expansion", true);
477 parser.setFeature ("http://apache.org/xml/features/dom/include-ignorable-whitespace", false);
478 parser.parse (isc);
479 document = parser.getDocument ();
480
481 } catch(SAXParseException e) {
482 showXMLParseFailureLine(e, xmlContents);
483 } catch (SAXException exception) {
484 System.err.println ("SAX exception: " + exception.getMessage ());
485 if(DebugStream.isDebuggingEnabled()) {
486 DebugStream.println("Encountered a SAX exception when parsing the following:\n*********START\n"
487 + xmlContents + "\n************END\n");
488 // Exit to let the user view the erroneous line/xml before it goes past the screen buffer?
489 DebugStream.println("Debug mode: Exiting the program as there was trouble parsing the XML...");
490 System.exit(-1);
491 }
492 // else, not running in debug mode, so don't exit after exception
493 System.out.println("***Turn debugging on (run GLI with -debug) to view the XML contents that could not be parsed.");
494 DebugStream.printStackTrace (exception);
495 }
496 catch (Exception exception) {
497 DebugStream.printStackTrace (exception);
498 }
499
500 return document;
501 }
502
503 /** Displays the line (string) where the SAXParseException occurred, given a String of the
504 * entire xml that was being parsed and the SAXParseException object that was caught.
505 * The messages are printed to DebugStream, so run GLI/FLI with -debug to view this output.
506 * @param xmlContents is the entire xml that was being parsed when the exception occurred
507 * @param e is the SAXParseException object that was thrown upon parsing the xmlContents.
508 */
509 public static void showXMLParseFailureLine(SAXParseException e, String xmlContents) {
510
511 // There should be no characters at all that preceed the <?xml>... bit.
512 // The first check is for starting spaces:
513 if(xmlContents.startsWith("\n") || xmlContents.startsWith(" ") || xmlContents.startsWith("\t")) {
514 DebugStream.println("ERROR: illegal start of XML. Space/tab/newline should not preceed xml declaration.\n");
515 DebugStream.println("xmlContents (length is " + xmlContents.length() + "):\n" + xmlContents);
516 return; // nothing more to do, first error identified
517 }
518
519 // the actual line (String literal) where parsing failed and the SAXParseException occurred.
520 String line = "";
521 int linenumber = e.getLineNumber();
522 DebugStream.print("\n****SAXParseException on LINE NUMBER: " + linenumber);
523 if(DebugStream.isDebuggingEnabled()) {
524 if(linenumber != -1) {
525 String[] lines = xmlContents.split("\n");
526 if (lines.length > 0) {
527 DebugStream.println(" (number of lines: " + lines.length + ")");
528 if(lines.length >= linenumber) {
529 line = lines[linenumber-1];
530 } else { // error is past the last line
531 line = "Error is past the last line (" + lines.length + "): " + lines[lines.length-1];
532 }
533 } else {
534 DebugStream.print("\n");
535 }
536 lines = null;
537
538 DebugStream.println("The parsing error occurred on this line:\n***********START\n" + line + "\n***********END");
539 DebugStream.println("SAXParseException message: " + e.getMessage() + "\n");
540 } else { // no particular line number, print out all the xml so debugger can inspect it
541 DebugStream.println("Encountered a SAX exception when parsing the following:\n*********START\n"
542 + xmlContents + "\n************END\n");
543 }
544 // Exit to let the user view the erroneous line/xml before it goes past the screen buffer?
545 DebugStream.println("\nDebug mode: Exiting the program as there was trouble parsing the XML...");
546 System.exit(-1);
547 } else { // not running in debug mode
548 System.out.println("***Turn debugging on (run GLI with -debug) to view the XML contents/line that could not be parsed.");
549 }
550 }
551
552
553 static public StringBuffer readXMLStream (InputStream input_stream) {
554 StringBuffer xml = new StringBuffer ("");
555
556 try {
557 InputStreamReader isr = new InputStreamReader (input_stream, "UTF-8");
558 BufferedReader buffered_in = new BufferedReader (isr);
559
560 String line = "";
561 boolean xml_content = false;
562 while((line = buffered_in.readLine ()) != null) {
563 if(xml_content) {
564 xml.append (line);
565 xml.append ("\n");
566 }
567 else if(line.trim ().startsWith ("<?xml")) {
568 xml_content = true;
569 xml.append (line);
570 xml.append ("\n");
571 }
572 }
573 buffered_in = null;
574 }
575 catch (Exception error) {
576 System.err.println ("Failed when trying to parse XML stream");
577 error.printStackTrace ();
578 }
579
580 return xml;
581 }
582
583
584 /** Removes characters that are invalid in XML (see http://www.w3.org/TR/2000/REC-xml-20001006#charsets) */
585 static public String removeInvalidCharacters (String text) {
586 char[] safe_characters = new char[text.length ()];
587 int j = 0;
588
589 char[] raw_characters = new char[text.length ()];
590 text.getChars (0, text.length (), raw_characters, 0);
591 for (int i = 0; i < raw_characters.length; i++) {
592 char character = raw_characters[i];
593 if ((character >= 0x20 && character <= 0xD7FF) || character == 0x09 || character == 0x0A || character == 0x0D || (character >= 0xE000 && character <= 0xFFFD) || (character >= 0x10000 && character <= 0x10FFFF)) {
594 safe_characters[j] = character;
595 j++;
596 }
597 }
598
599 return new String (safe_characters, 0, j);
600 }
601
602
603 static public void setElementTextValue (Element element, String text) {
604 // Remove all text node children
605 NodeList children_nodelist = element.getChildNodes ();
606 for (int i = children_nodelist.getLength () - 1; i >= 0; i--) {
607 Node child_node = children_nodelist.item (i);
608 if (child_node.getNodeType () == Node.TEXT_NODE) {
609 element.removeChild (child_node);
610 }
611 }
612
613 // Add a new text node
614 if (text != null) {
615 element.appendChild (element.getOwnerDocument ().createTextNode (text));
616 }
617 }
618
619
620 /** Set the #text node value of some element.
621 * @param element the Element whose value we wish to set
622 * @param value the new value for the element as a String
623 * Soon to be deprecated!
624 */
625 static final public void setValue (Element element, String value) {
626 // Remove any existing child node(s)
627 clear (element);
628 // Add new text node.
629 if (value != null) {
630 element.appendChild (element.getOwnerDocument ().createTextNode (value));
631 }
632 }
633
634 /** Write an XML document to a given file with the text node of the specified element unescaped*/
635 static public void writeXMLFile (File xml_file, Document document, String[] nonEscapingTagNames) {
636 try {
637 OutputStream os = new FileOutputStream (xml_file);
638 // Create an output format for our document.
639 OutputFormat f = new OutputFormat (document);
640 f.setEncoding ("UTF-8");
641 f.setIndenting (true);
642 f.setLineWidth (0); // Why isn't this working!
643 f.setPreserveSpace (false);
644 if (nonEscapingTagNames != null) {
645 f.setNonEscapingElements (nonEscapingTagNames);
646 }
647 // Create the necessary writer stream for serialization.
648 OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8");
649 Writer w = new BufferedWriter (osw);
650 // Generate a new serializer from the above.
651 XMLSerializer s = new XMLSerializer (w, f);
652 s.asDOMSerializer ();
653 // Finally serialize the document to file.
654 s.serialize (document);
655 // And close.
656 os.close ();
657 }
658 catch (Exception exception) {
659 DebugStream.printStackTrace (exception);
660 }
661 }
662
663 /** Write an XML document to a given file */
664 static public void writeXMLFile (File xml_file, Document document) {
665 writeXMLFile(xml_file, document, null);
666 }
667
668 public static void printXMLNode (Node e) {
669 printXMLNode (e, 0) ;
670 }
671
672 public static void printXMLNode (Node e, int depth) { //recursive method call using DOM API...
673
674 for (int i=0 ; i<depth ; i++)
675 System.out.print (' ') ;
676
677 if (e.getNodeType () == Node.TEXT_NODE){
678 //System.out.println("text") ;
679 if (e.getNodeValue () != "") {
680 System.out.println (e.getNodeValue ()) ;
681 }
682 return ;
683 }
684
685 System.out.print ('<');
686 System.out.print (e.getNodeName ());
687 NamedNodeMap attrs = e.getAttributes ();
688 if (attrs != null) {
689 for (int i = 0; i < attrs.getLength (); i++) {
690 Node attr = attrs.item (i);
691 System.out.print (' ');
692 System.out.print (attr.getNodeName ());
693 System.out.print ("=\"");
694 System.out.print (attr.getNodeValue ());
695 System.out.print ('"');
696 }
697 }
698 NodeList children = e.getChildNodes ();
699
700 if (children == null || children.getLength () == 0)
701 System.out.println ("/>") ;
702 else {
703
704 System.out.println ('>') ;
705
706 int len = children.getLength ();
707 for (int i = 0; i < len; i++) {
708 printXMLNode (children.item (i), depth + 1);
709 }
710
711 for (int i=0 ; i<depth ; i++)
712 System.out.print (' ') ;
713
714 System.out.println ("</" + e.getNodeName () + ">");
715 }
716
717 }
718 public static String xmlNodeToString (Node e){
719 StringBuffer sb = new StringBuffer ("");
720 xmlNodeToString (sb,e,0);
721 return sb.toString ();
722 }
723
724 private static void xmlNodeToString (StringBuffer sb, Node e, int depth){
725
726 for (int i=0 ; i<depth ; i++)
727 sb.append (' ') ;
728
729 if (e.getNodeType () == Node.TEXT_NODE){
730 if (e.getNodeValue () != "") {
731 sb.append (e.getNodeValue ()) ;
732 }
733 return ;
734 }
735
736 sb.append ('<');
737 sb.append (e.getNodeName ());
738 NamedNodeMap attrs = e.getAttributes ();
739 if (attrs != null) {
740 for (int i = 0; i < attrs.getLength (); i++) {
741 Node attr = attrs.item (i);
742 sb.append (' ');
743 sb.append (attr.getNodeName ());
744 sb.append ("=\"");
745 sb.append (attr.getNodeValue ());
746 sb.append ('"');
747 }
748 }
749 NodeList children = e.getChildNodes ();
750
751 if (children == null || children.getLength () == 0)
752 sb.append ("/>\n") ;
753 else {
754
755 sb.append (">\n") ;
756
757 int len = children.getLength ();
758 for (int i = 0; i < len; i++) {
759 xmlNodeToString (sb,children.item (i), depth + 1);
760 }
761
762 for (int i=0 ; i<depth ; i++)
763 sb.append (' ') ;
764
765 sb.append ("</" + e.getNodeName () + ">\n");
766 }
767
768
769 }
770
771 public static String xmlNodeToStringWithoutIndenting (Node e) {
772 StringBuffer sb = new StringBuffer ("");
773 xmlNodeToStringWithoutNewline(sb, e, -1);
774 return sb.toString();
775 }
776 public static String xmlNodeToStringWithoutNewline (Node e){
777 StringBuffer sb = new StringBuffer ("");
778 xmlNodeToStringWithoutNewline (sb,e,0);
779 return sb.toString ();
780 }
781
782 private static void xmlNodeToStringWithoutNewline (StringBuffer sb, Node e, int depth){
783
784 for (int i=0 ; i<depth ; i++)
785 sb.append (' ') ;
786
787 if (e.getNodeType () == Node.TEXT_NODE){
788 if (e.getNodeValue () != "") {
789 sb.append (e.getNodeValue ()) ;
790 }
791 return ;
792 }
793
794 sb.append ('<');
795 sb.append (e.getNodeName ());
796 NamedNodeMap attrs = e.getAttributes ();
797 if (attrs != null) {
798 for (int i = 0; i < attrs.getLength (); i++) {
799 Node attr = attrs.item (i);
800 sb.append (' ');
801 sb.append (attr.getNodeName ());
802 sb.append ("=\"");
803 sb.append (attr.getNodeValue ());
804 sb.append ('"');
805 }
806 }
807 NodeList children = e.getChildNodes ();
808
809 if (children == null || children.getLength () == 0)
810 sb.append ("/>") ;
811 else {
812
813 sb.append (">") ;
814
815 int len = children.getLength ();
816 for (int i = 0; i < len; i++) {
817 if (depth >= 0) {
818 xmlNodeToStringWithoutNewline (sb,children.item (i), depth + 1);
819 } else {
820 xmlNodeToStringWithoutNewline (sb,children.item (i), depth);
821 }
822 }
823
824 for (int i=0 ; i<depth ; i++)
825 sb.append (' ') ;
826
827 sb.append ("</" + e.getNodeName () + ">");
828 }
829 }
830}
Note: See TracBrowser for help on using the repository browser.