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

Last change on this file since 14053 was 14053, checked in by xiao, 17 years ago

add some new xml methods.

  • Property svn:keywords set to Author Date Id Revision
File size: 27.6 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 /** Parse an XML document from a given file path */
375 static public Document parseXMLFile (String xml_file_path, boolean use_class_loader) {
376 if (use_class_loader == true) {
377 InputStream is = JarTools.getResourceAsStream ("/" + xml_file_path);
378 if (is != null) {
379 return parseXML (is);
380 }
381 }
382
383 // Try the file outside the classes directory
384 return parseXMLFile (new File (xml_file_path));
385 }
386
387
388 /** Parse an XML document from a given file */
389 static public Document parseXMLFile (File xml_file) {
390 // No file? No point trying!
391 if (xml_file.exists () == false) {
392 return null;
393 }
394
395 try {
396 return parseXML (new FileInputStream (xml_file));
397 }
398 catch (Exception exception) {
399 DebugStream.printStackTrace (exception);
400 return null;
401 }
402 }
403
404
405 /** Parse an XML document from a given input stream */
406 static public Document parseXML (InputStream xml_input_stream) {
407 Document document = null;
408
409 try {
410 InputStreamReader isr = new InputStreamReader (xml_input_stream, "UTF-8");
411 Reader xml_reader = new BufferedReader (isr);
412 document = parseXML (xml_reader);
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 try {
429 InputSource isc = new InputSource (xml_reader);
430 DOMParser parser = new DOMParser ();
431 parser.setFeature ("http://xml.org/sax/features/validation", false);
432 parser.setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
433 // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster.
434 parser.setFeature ("http://apache.org/xml/features/dom/defer-node-expansion", true);
435 parser.setFeature ("http://apache.org/xml/features/dom/include-ignorable-whitespace", false);
436 parser.parse (isc);
437 document = parser.getDocument ();
438 }
439 catch (SAXException exception) {
440 System.err.println ("SAX exception: " + exception.getMessage ());
441 DebugStream.printStackTrace (exception);
442 }
443 catch (Exception exception) {
444 DebugStream.printStackTrace (exception);
445 }
446
447 return document;
448 }
449
450
451 static public StringBuffer readXMLStream (InputStream input_stream) {
452 StringBuffer xml = new StringBuffer ("");
453
454 try {
455 InputStreamReader isr = new InputStreamReader (input_stream, "UTF-8");
456 BufferedReader buffered_in = new BufferedReader (isr);
457
458 String line = "";
459 boolean xml_content = false;
460 while((line = buffered_in.readLine ()) != null) {
461 if(xml_content) {
462 xml.append (line);
463 xml.append ("\n");
464 }
465 else if(line.trim ().startsWith ("<?xml")) {
466 xml_content = true;
467 xml.append (line);
468 xml.append ("\n");
469 }
470 }
471 buffered_in = null;
472 }
473 catch (Exception error) {
474 System.err.println ("Failed when trying to parse XML stream");
475 error.printStackTrace ();
476 }
477
478 return xml;
479 }
480
481
482 /** Removes characters that are invalid in XML (see http://www.w3.org/TR/2000/REC-xml-20001006#charsets) */
483 static public String removeInvalidCharacters (String text) {
484 char[] safe_characters = new char[text.length ()];
485 int j = 0;
486
487 char[] raw_characters = new char[text.length ()];
488 text.getChars (0, text.length (), raw_characters, 0);
489 for (int i = 0; i < raw_characters.length; i++) {
490 char character = raw_characters[i];
491 if ((character >= 0x20 && character <= 0xD7FF) || character == 0x09 || character == 0x0A || character == 0x0D || (character >= 0xE000 && character <= 0xFFFD) || (character >= 0x10000 && character <= 0x10FFFF)) {
492 safe_characters[j] = character;
493 j++;
494 }
495 }
496
497 return new String (safe_characters, 0, j);
498 }
499
500
501 static public void setElementTextValue (Element element, String text) {
502 // Remove all text node children
503 NodeList children_nodelist = element.getChildNodes ();
504 for (int i = children_nodelist.getLength () - 1; i >= 0; i--) {
505 Node child_node = children_nodelist.item (i);
506 if (child_node.getNodeType () == Node.TEXT_NODE) {
507 element.removeChild (child_node);
508 }
509 }
510
511 // Add a new text node
512 if (text != null) {
513 element.appendChild (element.getOwnerDocument ().createTextNode (text));
514 }
515 }
516
517
518 /** Set the #text node value of some element.
519 * @param element the Element whose value we wish to set
520 * @param value the new value for the element as a String
521 * Soon to be deprecated!
522 */
523 static final public void setValue (Element element, String value) {
524 // Remove any existing child node(s)
525 clear (element);
526 // Add new text node.
527 if (value != null) {
528 element.appendChild (element.getOwnerDocument ().createTextNode (value));
529 }
530 }
531
532 /** Write an XML document to a given file with the text node of the specified element unescaped*/
533 static public void writeXMLFile (File xml_file, Document document, String[] nonEscapingTagNames) {
534 try {
535 OutputStream os = new FileOutputStream (xml_file);
536 // Create an output format for our document.
537 OutputFormat f = new OutputFormat (document);
538 f.setEncoding ("UTF-8");
539 f.setIndenting (true);
540 f.setLineWidth (0); // Why isn't this working!
541 f.setPreserveSpace (false);
542
543 f.setNonEscapingElements (nonEscapingTagNames);
544 // Create the necessary writer stream for serialization.
545 OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8");
546 Writer w = new BufferedWriter (osw);
547 // Generate a new serializer from the above.
548 XMLSerializer s = new XMLSerializer (w, f);
549 s.asDOMSerializer ();
550 // Finally serialize the document to file.
551 s.serialize (document);
552 // And close.
553 os.close ();
554 }
555 catch (Exception exception) {
556 DebugStream.printStackTrace (exception);
557 }
558 }
559
560 /** Write an XML document to a given file */
561 static public void writeXMLFile (File xml_file, Document document) {
562 try {
563 OutputStream os = new FileOutputStream (xml_file);
564 // Create an output format for our document.
565 OutputFormat f = new OutputFormat (document);
566 f.setEncoding ("UTF-8");
567 f.setIndenting (true);
568 f.setLineWidth (0); // Why isn't this working!
569 f.setPreserveSpace (false);
570 // Create the necessary writer stream for serialization.
571 OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8");
572 Writer w = new BufferedWriter (osw);
573 // Generate a new serializer from the above.
574 XMLSerializer s = new XMLSerializer (w, f);
575 s.asDOMSerializer ();
576 // Finally serialize the document to file.
577 s.serialize (document);
578 // And close.
579 os.close ();
580 }
581 catch (Exception exception) {
582 DebugStream.printStackTrace (exception);
583 }
584 }
585
586 public static void printXMLNode (Node e) {
587 printXMLNode (e, 0) ;
588 }
589
590 public static void printXMLNode (Node e, int depth) { //recursive method call using DOM API...
591
592 for (int i=0 ; i<depth ; i++)
593 System.out.print (' ') ;
594
595 if (e.getNodeType () == Node.TEXT_NODE){
596 //System.out.println("text") ;
597 if (e.getNodeValue () != "") {
598 System.out.println (e.getNodeValue ()) ;
599 }
600 return ;
601 }
602
603 System.out.print ('<');
604 System.out.print (e.getNodeName ());
605 NamedNodeMap attrs = e.getAttributes ();
606 if (attrs != null) {
607 for (int i = 0; i < attrs.getLength (); i++) {
608 Node attr = attrs.item (i);
609 System.out.print (' ');
610 System.out.print (attr.getNodeName ());
611 System.out.print ("=\"");
612 System.out.print (attr.getNodeValue ());
613 System.out.print ('"');
614 }
615 }
616 NodeList children = e.getChildNodes ();
617
618 if (children == null || children.getLength () == 0)
619 System.out.println ("/>") ;
620 else {
621
622 System.out.println ('>') ;
623
624 int len = children.getLength ();
625 for (int i = 0; i < len; i++) {
626 printXMLNode (children.item (i), depth + 1);
627 }
628
629 for (int i=0 ; i<depth ; i++)
630 System.out.print (' ') ;
631
632 System.out.println ("</" + e.getNodeName () + ">");
633 }
634
635 }
636 public static String xmlNodeToString (Node e){
637 StringBuffer sb = new StringBuffer ("");
638 xmlNodeToString (sb,e,0);
639 return sb.toString ();
640 }
641
642 private static void xmlNodeToString (StringBuffer sb, Node e, int depth){
643
644 for (int i=0 ; i<depth ; i++)
645 sb.append (' ') ;
646
647 if (e.getNodeType () == Node.TEXT_NODE){
648 if (e.getNodeValue () != "") {
649 sb.append (e.getNodeValue ()) ;
650 }
651 return ;
652 }
653
654 sb.append ('<');
655 sb.append (e.getNodeName ());
656 NamedNodeMap attrs = e.getAttributes ();
657 if (attrs != null) {
658 for (int i = 0; i < attrs.getLength (); i++) {
659 Node attr = attrs.item (i);
660 sb.append (' ');
661 sb.append (attr.getNodeName ());
662 sb.append ("=\"");
663 sb.append (attr.getNodeValue ());
664 sb.append ('"');
665 }
666 }
667 NodeList children = e.getChildNodes ();
668
669 if (children == null || children.getLength () == 0)
670 sb.append ("/>\n") ;
671 else {
672
673 sb.append (">\n") ;
674
675 int len = children.getLength ();
676 for (int i = 0; i < len; i++) {
677 xmlNodeToString (sb,children.item (i), depth + 1);
678 }
679
680 for (int i=0 ; i<depth ; i++)
681 sb.append (' ') ;
682
683 sb.append ("</" + e.getNodeName () + ">\n");
684 }
685
686
687 }
688 public static String xmlNodeToStringWithoutNewline (Node e){
689 StringBuffer sb = new StringBuffer ("");
690 xmlNodeToStringWithoutNewline (sb,e,0);
691 return sb.toString ();
692 }
693
694 private static void xmlNodeToStringWithoutNewline (StringBuffer sb, Node e, int depth){
695
696 for (int i=0 ; i<depth ; i++)
697 sb.append (' ') ;
698
699 if (e.getNodeType () == Node.TEXT_NODE){
700 if (e.getNodeValue () != "") {
701 sb.append (e.getNodeValue ()) ;
702 }
703 return ;
704 }
705
706 sb.append ('<');
707 sb.append (e.getNodeName ());
708 NamedNodeMap attrs = e.getAttributes ();
709 if (attrs != null) {
710 for (int i = 0; i < attrs.getLength (); i++) {
711 Node attr = attrs.item (i);
712 sb.append (' ');
713 sb.append (attr.getNodeName ());
714 sb.append ("=\"");
715 sb.append (attr.getNodeValue ());
716 sb.append ('"');
717 }
718 }
719 NodeList children = e.getChildNodes ();
720
721 if (children == null || children.getLength () == 0)
722 sb.append ("/>") ;
723 else {
724
725 sb.append (">") ;
726
727 int len = children.getLength ();
728 for (int i = 0; i < len; i++) {
729 xmlNodeToStringWithoutNewline (sb,children.item (i), depth + 1);
730 }
731
732 for (int i=0 ; i<depth ; i++)
733 sb.append (' ') ;
734
735 sb.append ("</" + e.getNodeName () + ">");
736 }
737
738
739 }
740
741}
Note: See TracBrowser for help on using the repository browser.