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

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

Useful debugging statement, left commented out. Can be used to look at the XML sent in to fix any outstanding issues with the recent changes to XML parsing.

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