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

Last change on this file since 18170 was 18170, checked in by oranfry, 15 years ago

merged in code to do error reporting on xml parsing, even without debug mode on

  • Property svn:keywords set to Author Date Id Revision
File size: 32.5 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 }
468
469 // (2) The actual XML parsing
470 InputSource isc = new InputSource (reader);
471 DOMParser parser = new DOMParser ();
472 parser.setFeature ("http://xml.org/sax/features/validation", false);
473 parser.setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
474 // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster.
475 parser.setFeature ("http://apache.org/xml/features/dom/defer-node-expansion", true);
476 parser.setFeature ("http://apache.org/xml/features/dom/include-ignorable-whitespace", false);
477 parser.parse (isc);
478 document = parser.getDocument ();
479
480 } catch(SAXParseException e) {
481 showXMLParseFailureLine(e, xmlContents);
482 } catch (SAXException exception) {
483 System.err.println ("SAX exception: " + exception.getMessage ());
484 if(DebugStream.isDebuggingEnabled()) {
485 DebugStream.println("Encountered a SAX exception when parsing the following:\n*********START\n"
486 + xmlContents + "\n************END\n");
487 // Exit to let the user view the erroneous line/xml before it goes past the screen buffer?
488 DebugStream.println("Debug mode: Exiting the program as there was trouble parsing the XML...");
489 System.exit(-1);
490 }
491 // else, not running in debug mode, so don't exit after exception
492 System.out.println("***Turn debugging on (run GLI with -debug) to view the XML contents that could not be parsed.");
493 DebugStream.printStackTrace (exception);
494 }
495 catch (Exception exception) {
496 DebugStream.printStackTrace (exception);
497 }
498
499 return document;
500 }
501
502 /** Displays the line (string) where the SAXParseException occurred, given a String of the
503 * entire xml that was being parsed and the SAXParseException object that was caught.
504 * The messages are printed to DebugStream, so run GLI/FLI with -debug to view this output.
505 * @param xmlContents is the entire xml that was being parsed when the exception occurred
506 * @param e is the SAXParseException object that was thrown upon parsing the xmlContents.
507 */
508 public static void showXMLParseFailureLine(SAXParseException e, String xmlContents) {
509
510 // There should be no characters at all that preceed the <?xml>... bit.
511 // The first check is for starting spaces:
512 if(xmlContents.startsWith("\n") || xmlContents.startsWith(" ") || xmlContents.startsWith("\t")) {
513 DebugStream.println("ERROR: illegal start of XML. Space/tab/newline should not preceed xml declaration.\n");
514 DebugStream.println("xmlContents (length is " + xmlContents.length() + "):\n" + xmlContents);
515 return; // nothing more to do, first error identified
516 }
517
518 // the actual line (String literal) where parsing failed and the SAXParseException occurred.
519 String line = "";
520 int linenumber = e.getLineNumber();
521 DebugStream.println("\n****SAXParseException on LINE NUMBER: " + linenumber);
522 if(DebugStream.isDebuggingEnabled()) {
523 if(linenumber != -1) {
524 // find the line in xmlContents string (xmlContents is only set if GLI is run with debugging turned on)
525 int start = 0;
526 int end = xmlContents.length();
527 for(int i = 1; i <= linenumber; i++) {
528 end = xmlContents.indexOf("\n");
529 if(end > 0) {
530 line = xmlContents.substring(start, end);
531 }
532 start = end+1;
533 }
534 DebugStream.println("The parsing error occurred on this line:\n***********START\n" + line + "\n***********END");
535 DebugStream.println("SAXParseException message: " + e.getMessage() + "\n");
536 } else { // no particular line number, print out all the xml so debugger can inspect it
537 DebugStream.println("Encountered a SAX exception when parsing the following:\n*********START\n"
538 + xmlContents + "\n************END\n");
539 }
540 // Exit to let the user view the erroneous line/xml before it goes past the screen buffer?
541 DebugStream.println("\nDebug mode: Exiting the program as there was trouble parsing the XML...");
542 System.exit(-1);
543 } else { // not running in debug mode
544 System.out.println("***Turn debugging on (run GLI with -debug) to view the XML contents/line that could not be parsed.");
545 }
546 }
547
548
549 static public StringBuffer readXMLStream (InputStream input_stream) {
550 StringBuffer xml = new StringBuffer ("");
551
552 try {
553 InputStreamReader isr = new InputStreamReader (input_stream, "UTF-8");
554 BufferedReader buffered_in = new BufferedReader (isr);
555
556 String line = "";
557 boolean xml_content = false;
558 while((line = buffered_in.readLine ()) != null) {
559 if(xml_content) {
560 xml.append (line);
561 xml.append ("\n");
562 }
563 else if(line.trim ().startsWith ("<?xml")) {
564 xml_content = true;
565 xml.append (line);
566 xml.append ("\n");
567 }
568 }
569 buffered_in = null;
570 }
571 catch (Exception error) {
572 System.err.println ("Failed when trying to parse XML stream");
573 error.printStackTrace ();
574 }
575
576 return xml;
577 }
578
579
580 /** Removes characters that are invalid in XML (see http://www.w3.org/TR/2000/REC-xml-20001006#charsets) */
581 static public String removeInvalidCharacters (String text) {
582 char[] safe_characters = new char[text.length ()];
583 int j = 0;
584
585 char[] raw_characters = new char[text.length ()];
586 text.getChars (0, text.length (), raw_characters, 0);
587 for (int i = 0; i < raw_characters.length; i++) {
588 char character = raw_characters[i];
589 if ((character >= 0x20 && character <= 0xD7FF) || character == 0x09 || character == 0x0A || character == 0x0D || (character >= 0xE000 && character <= 0xFFFD) || (character >= 0x10000 && character <= 0x10FFFF)) {
590 safe_characters[j] = character;
591 j++;
592 }
593 }
594
595 return new String (safe_characters, 0, j);
596 }
597
598
599 static public void setElementTextValue (Element element, String text) {
600 // Remove all text node children
601 NodeList children_nodelist = element.getChildNodes ();
602 for (int i = children_nodelist.getLength () - 1; i >= 0; i--) {
603 Node child_node = children_nodelist.item (i);
604 if (child_node.getNodeType () == Node.TEXT_NODE) {
605 element.removeChild (child_node);
606 }
607 }
608
609 // Add a new text node
610 if (text != null) {
611 element.appendChild (element.getOwnerDocument ().createTextNode (text));
612 }
613 }
614
615
616 /** Set the #text node value of some element.
617 * @param element the Element whose value we wish to set
618 * @param value the new value for the element as a String
619 * Soon to be deprecated!
620 */
621 static final public void setValue (Element element, String value) {
622 // Remove any existing child node(s)
623 clear (element);
624 // Add new text node.
625 if (value != null) {
626 element.appendChild (element.getOwnerDocument ().createTextNode (value));
627 }
628 }
629
630 /** Write an XML document to a given file with the text node of the specified element unescaped*/
631 static public void writeXMLFile (File xml_file, Document document, String[] nonEscapingTagNames) {
632 try {
633 OutputStream os = new FileOutputStream (xml_file);
634 // Create an output format for our document.
635 OutputFormat f = new OutputFormat (document);
636 f.setEncoding ("UTF-8");
637 f.setIndenting (true);
638 f.setLineWidth (0); // Why isn't this working!
639 f.setPreserveSpace (false);
640 if (nonEscapingTagNames != null) {
641 f.setNonEscapingElements (nonEscapingTagNames);
642 }
643 // Create the necessary writer stream for serialization.
644 OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8");
645 Writer w = new BufferedWriter (osw);
646 // Generate a new serializer from the above.
647 XMLSerializer s = new XMLSerializer (w, f);
648 s.asDOMSerializer ();
649 // Finally serialize the document to file.
650 s.serialize (document);
651 // And close.
652 os.close ();
653 }
654 catch (Exception exception) {
655 DebugStream.printStackTrace (exception);
656 }
657 }
658
659 /** Write an XML document to a given file */
660 static public void writeXMLFile (File xml_file, Document document) {
661 writeXMLFile(xml_file, document, null);
662 }
663
664 public static void printXMLNode (Node e) {
665 printXMLNode (e, 0) ;
666 }
667
668 public static void printXMLNode (Node e, int depth) { //recursive method call using DOM API...
669
670 for (int i=0 ; i<depth ; i++)
671 System.out.print (' ') ;
672
673 if (e.getNodeType () == Node.TEXT_NODE){
674 //System.out.println("text") ;
675 if (e.getNodeValue () != "") {
676 System.out.println (e.getNodeValue ()) ;
677 }
678 return ;
679 }
680
681 System.out.print ('<');
682 System.out.print (e.getNodeName ());
683 NamedNodeMap attrs = e.getAttributes ();
684 if (attrs != null) {
685 for (int i = 0; i < attrs.getLength (); i++) {
686 Node attr = attrs.item (i);
687 System.out.print (' ');
688 System.out.print (attr.getNodeName ());
689 System.out.print ("=\"");
690 System.out.print (attr.getNodeValue ());
691 System.out.print ('"');
692 }
693 }
694 NodeList children = e.getChildNodes ();
695
696 if (children == null || children.getLength () == 0)
697 System.out.println ("/>") ;
698 else {
699
700 System.out.println ('>') ;
701
702 int len = children.getLength ();
703 for (int i = 0; i < len; i++) {
704 printXMLNode (children.item (i), depth + 1);
705 }
706
707 for (int i=0 ; i<depth ; i++)
708 System.out.print (' ') ;
709
710 System.out.println ("</" + e.getNodeName () + ">");
711 }
712
713 }
714 public static String xmlNodeToString (Node e){
715 StringBuffer sb = new StringBuffer ("");
716 xmlNodeToString (sb,e,0);
717 return sb.toString ();
718 }
719
720 private static void xmlNodeToString (StringBuffer sb, Node e, int depth){
721
722 for (int i=0 ; i<depth ; i++)
723 sb.append (' ') ;
724
725 if (e.getNodeType () == Node.TEXT_NODE){
726 if (e.getNodeValue () != "") {
727 sb.append (e.getNodeValue ()) ;
728 }
729 return ;
730 }
731
732 sb.append ('<');
733 sb.append (e.getNodeName ());
734 NamedNodeMap attrs = e.getAttributes ();
735 if (attrs != null) {
736 for (int i = 0; i < attrs.getLength (); i++) {
737 Node attr = attrs.item (i);
738 sb.append (' ');
739 sb.append (attr.getNodeName ());
740 sb.append ("=\"");
741 sb.append (attr.getNodeValue ());
742 sb.append ('"');
743 }
744 }
745 NodeList children = e.getChildNodes ();
746
747 if (children == null || children.getLength () == 0)
748 sb.append ("/>\n") ;
749 else {
750
751 sb.append (">\n") ;
752
753 int len = children.getLength ();
754 for (int i = 0; i < len; i++) {
755 xmlNodeToString (sb,children.item (i), depth + 1);
756 }
757
758 for (int i=0 ; i<depth ; i++)
759 sb.append (' ') ;
760
761 sb.append ("</" + e.getNodeName () + ">\n");
762 }
763
764
765 }
766
767 public static String xmlNodeToStringWithoutIndenting (Node e) {
768 StringBuffer sb = new StringBuffer ("");
769 xmlNodeToStringWithoutNewline(sb, e, -1);
770 return sb.toString();
771 }
772 public static String xmlNodeToStringWithoutNewline (Node e){
773 StringBuffer sb = new StringBuffer ("");
774 xmlNodeToStringWithoutNewline (sb,e,0);
775 return sb.toString ();
776 }
777
778 private static void xmlNodeToStringWithoutNewline (StringBuffer sb, Node e, int depth){
779
780 for (int i=0 ; i<depth ; i++)
781 sb.append (' ') ;
782
783 if (e.getNodeType () == Node.TEXT_NODE){
784 if (e.getNodeValue () != "") {
785 sb.append (e.getNodeValue ()) ;
786 }
787 return ;
788 }
789
790 sb.append ('<');
791 sb.append (e.getNodeName ());
792 NamedNodeMap attrs = e.getAttributes ();
793 if (attrs != null) {
794 for (int i = 0; i < attrs.getLength (); i++) {
795 Node attr = attrs.item (i);
796 sb.append (' ');
797 sb.append (attr.getNodeName ());
798 sb.append ("=\"");
799 sb.append (attr.getNodeValue ());
800 sb.append ('"');
801 }
802 }
803 NodeList children = e.getChildNodes ();
804
805 if (children == null || children.getLength () == 0)
806 sb.append ("/>") ;
807 else {
808
809 sb.append (">") ;
810
811 int len = children.getLength ();
812 for (int i = 0; i < len; i++) {
813 if (depth >= 0) {
814 xmlNodeToStringWithoutNewline (sb,children.item (i), depth + 1);
815 } else {
816 xmlNodeToStringWithoutNewline (sb,children.item (i), depth);
817 }
818 }
819
820 for (int i=0 ; i<depth ; i++)
821 sb.append (' ') ;
822
823 sb.append ("</" + e.getNodeName () + ">");
824 }
825 }
826}
Note: See TracBrowser for help on using the repository browser.