KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > app > webui > util > DCInputsReader


1 /*
2  * DCInputsReader.java
3  *
4  * Version: $Revision: 1.5 $
5  *
6  * Date: $Date: 2006/11/27 23:51:16 $
7  *
8  * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
9  * Institute of Technology. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are
13  * met:
14  *
15  * - Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * - Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * - Neither the name of the Hewlett-Packard Company nor the name of the
23  * Massachusetts Institute of Technology nor the names of their
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  */

40
41 package org.dspace.app.webui.util;
42
43 import java.io.File JavaDoc;
44 import java.util.Vector JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.Iterator JavaDoc;
47 import java.lang.Exception JavaDoc;
48 import javax.servlet.ServletException JavaDoc;
49 import org.xml.sax.SAXException JavaDoc;
50 import org.w3c.dom.*;
51 import javax.xml.parsers.*;
52
53 import org.apache.log4j.Logger;
54
55 import org.dspace.content.MetadataSchema;
56 import org.dspace.core.ConfigurationManager;
57 import org.dspace.app.webui.servlet.SubmitServlet;
58
59 /**
60  * Submission form generator for DSpace. Reads and parses the installation
61  * form definitions file, input-forms.xml, from the configuration directory.
62  * A forms definition details the page and field layout of the metadata
63  * collection pages used by the submission process. Each forms definition
64  * starts with a unique name that gets associated with that form set.
65  *
66  * The file also specifies which collections use which form sets. At a
67  * minimum, the definitions file must define a default mapping from the
68  * placeholder collection #0 to the distinguished form 'default'. Any
69  * collections that use a custom form set are listed paired with the name
70  * of the form set they use.
71  *
72  * The definitions file also may contain sets of value pairs. Each value pair
73  * will contain one string that the user reads, and a paired string that will
74  * supply the value stored in the database if its sibling display value gets
75  * selected from a choice list.
76  *
77  * @author Brian S. Hughes
78  * @version $Revision: 1.5 $
79  */

80
81 public class DCInputsReader
82 {
83     /** The ID of the default collection. Will never be the ID of a named collection */
84     static final String JavaDoc DEFAULT_COLLECTION = "default";
85
86     /** Name of the form definition XML file */
87     static final String JavaDoc FORM_DEF_FILE = "input-forms.xml";
88
89     /** Keyname for storing dropdown value-pair set name */
90     static final String JavaDoc PAIR_TYPE_NAME = "value-pairs-name";
91
92     /** log4j logger */
93     private static Logger log = Logger.getLogger(DCInputsReader.class);
94
95     /** The fully qualified pathname of the form definition XML file */
96     private String JavaDoc defsFile = ConfigurationManager.getProperty("dspace.dir") +
97         File.separator + "config" + File.separator + FORM_DEF_FILE;
98
99     /** Reference to the collections to forms map,
100      * computed from the forms definition file
101      */

102     private HashMap JavaDoc whichForms = null;
103
104     /** Reference to the forms definitions map,
105      * computed from the forms definition file
106      */

107     private HashMap JavaDoc formDefns = null;
108
109     /** Reference to the value-pairs map,
110      * computed from the forms defition file
111      */

112     private HashMap JavaDoc valuePairs = null; // Holds display/storage pairs
113

114     /**
115      * Mini-cache of last DCInputSet requested. If submissions are not
116      * typically form-interleaved, there will be a modest win.
117      */

118     private DCInputSet lastInputSet = null;
119
120     /**
121      * Parse an XML encoded submission forms template file, and create
122      * a hashmap containing all the form information. This
123      * hashmap will contain three top level structures: a map between
124      * collections and forms, the definition for each page of each form,
125      * and lists of pairs of values that populate selection boxes.
126      */

127
128     public DCInputsReader()
129          throws ServletException JavaDoc
130     {
131         buildInputs(defsFile);
132     }
133
134
135     public DCInputsReader(String JavaDoc fileName)
136          throws ServletException JavaDoc
137     {
138         buildInputs(fileName);
139     }
140
141
142     private void buildInputs(String JavaDoc fileName)
143          throws ServletException JavaDoc
144     {
145         whichForms = new HashMap JavaDoc();
146         formDefns = new HashMap JavaDoc();
147         valuePairs = new HashMap JavaDoc();
148
149         String JavaDoc uri = "file:" + new File JavaDoc(fileName).getAbsolutePath();
150
151         try
152         {
153             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
154             factory.setValidating(false);
155             factory.setIgnoringComments(true);
156             factory.setIgnoringElementContentWhitespace(true);
157             
158             DocumentBuilder db = factory.newDocumentBuilder();
159             Document doc = db.parse(uri);
160             doNodes(doc);
161             checkValues();
162         }
163         catch (FactoryConfigurationError fe)
164         {
165             throw new ServletException JavaDoc("Cannot create Submission form parser",fe);
166         }
167         catch (Exception JavaDoc e)
168         {
169             throw new ServletException JavaDoc("Error creating submission forms: "+e);
170         }
171     }
172    
173     /**
174      * Returns the set of DC inputs used for a particular collection,
175      * or the default set if no inputs defined for the collection
176      * @param collectionHandle collection's unique Handle
177      * @return DC input set
178      * @throws ServletException if no default set defined
179      */

180     public DCInputSet getInputs(String JavaDoc collectionHandle)
181             throws ServletException JavaDoc
182     {
183         String JavaDoc formName = (String JavaDoc)whichForms.get(collectionHandle);
184         if (formName == null)
185         {
186             formName = (String JavaDoc)whichForms.get(DEFAULT_COLLECTION);
187         }
188         if (formName == null)
189         {
190             throw new ServletException JavaDoc("No form designated as default");
191         }
192         // check mini-cache, and return if match
193
if ( lastInputSet != null && lastInputSet.getFormName().equals( formName ) )
194         {
195             return lastInputSet;
196         }
197         // cache miss - construct new DCInputSet
198
Vector JavaDoc pages = (Vector JavaDoc)formDefns.get(formName);
199         if ( pages == null )
200         {
201             throw new ServletException JavaDoc("Missing the default form");
202         }
203         lastInputSet = new DCInputSet(formName, pages, valuePairs);
204         return lastInputSet;
205     }
206     
207     /**
208      * Return the number of pages the inputs span for a desginated collection
209      * @param collectionHandle collection's unique Handle
210      * @return number of pages of input
211      * @throws ServletException if no default set defined
212      */

213     public int getNumberInputPages(String JavaDoc collectionHandle)
214         throws ServletException JavaDoc
215     {
216         return getInputs(collectionHandle).getNumberPages();
217     }
218     
219     /**
220      * Process the top level child nodes in the passed top-level node.
221      * These should correspond to the collection-form maps, the form
222      * definitions, and the display/storage word pairs.
223      */

224     private void doNodes(Node n)
225         throws SAXException JavaDoc, ServletException JavaDoc
226     {
227         if (n == null)
228         {
229             return;
230         }
231         Node e = getElement(n);
232         NodeList nl = e.getChildNodes();
233         int len = nl.getLength();
234         boolean foundMap = false;
235         boolean foundDefs = false;
236         for (int i = 0; i < len; i++)
237         {
238             Node nd = nl.item(i);
239             if ((nd == null) || isEmptyTextNode(nd))
240             {
241                 continue;
242             }
243             String JavaDoc tagName = nd.getNodeName();
244             if (tagName.equals("form-map"))
245             {
246                 processMap(nd);
247                 foundMap = true;
248             }
249             else if (tagName.equals("form-definitions"))
250             {
251                 processDefinition(nd);
252                 foundDefs = true;
253             }
254             else if (tagName.equals("form-value-pairs"))
255             {
256                 processValuePairs(nd);
257             }
258             // Ignore unknown nodes
259
}
260         if (!foundMap)
261         {
262             throw new ServletException JavaDoc("No collection to form map found");
263         }
264         if (!foundDefs)
265         {
266             throw new ServletException JavaDoc("No form definition found");
267         }
268     }
269
270     /**
271      * Process the form-map section of the XML file.
272      * Each element looks like:
273      * <name-map collection-handle="hdl" form-name="name" />
274      * Extract the collection handle and form name, put name in hashmap keyed
275      * by the collection handle.
276      */

277     private void processMap(Node e)
278         throws SAXException JavaDoc
279     {
280         NodeList nl = e.getChildNodes();
281         int len = nl.getLength();
282         for (int i = 0; i < len; i++)
283         {
284             Node nd = nl.item(i);
285             if (nd.getNodeName().equals("name-map"))
286             {
287                 String JavaDoc id = getAttribute(nd, "collection-handle");
288                 String JavaDoc value = getAttribute(nd, "form-name");
289             String JavaDoc content = getValue(nd);
290                 if (id == null)
291                 {
292                     throw new SAXException JavaDoc("name-map element is missing collection-handle attribute");
293                 }
294             if (value == null)
295             {
296                 throw new SAXException JavaDoc("name-map element is missing form-name attribute");
297             }
298             if (content != null && content.length() > 0)
299             {
300                 throw new SAXException JavaDoc("name-map element has content, it should be empty.");
301             }
302                 whichForms.put(id, value);
303             } // ignore any child node that isn't a "name-map"
304
}
305     }
306
307     /**
308      * Process the form-definitions section of the XML file.
309      * Each element is formed thusly: <form name="formname">...pages...</form>
310      * Each pages subsection is formed: <page number="#"> ...fields... </page>
311      * Each field is formed from: dc-element, dc-qualifier, label, hint,
312      * input-type name, required text, and repeatable flag.
313      */

314     private void processDefinition(Node e)
315         throws SAXException JavaDoc, ServletException JavaDoc
316     {
317         int numForms = 0;
318         NodeList nl = e.getChildNodes();
319         int len = nl.getLength();
320         for (int i = 0; i < len; i++)
321         {
322             Node nd = nl.item(i);
323             // process each form definition
324
if (nd.getNodeName().equals("form"))
325             {
326                 numForms++;
327                 String JavaDoc formName = getAttribute(nd, "name");
328                 if (formName == null)
329                 {
330                     throw new SAXException JavaDoc("form element has no name attribute");
331                 }
332                 Vector JavaDoc pages = new Vector JavaDoc(); // the form contains pages
333
formDefns.put(formName, pages);
334                 NodeList pl = nd.getChildNodes();
335                 int lenpg = pl.getLength();
336                 for (int j = 0; j < lenpg; j++)
337                 {
338                     Node npg = pl.item(j);
339                     // process each page definition
340
if (npg.getNodeName().equals("page"))
341                     {
342                         String JavaDoc pgNum = getAttribute(npg, "number");
343                         if (pgNum == null)
344                         {
345                             throw new SAXException JavaDoc("Form " + formName + " has no identified pages");
346                         }
347                         Vector JavaDoc page = new Vector JavaDoc();
348                         pages.add(page);
349                         NodeList flds = npg.getChildNodes();
350                         int lenflds = flds.getLength();
351                         for (int k = 0; k < lenflds; k++)
352                         {
353                             Node nfld = flds.item(k);
354                             if ( nfld.getNodeName().equals("field") )
355                             {
356                                 // process each field definition
357
HashMap JavaDoc field = new HashMap JavaDoc();
358                                 page.add(field);
359                                 processPageParts(formName, pgNum, nfld, field);
360                                 String JavaDoc error = checkForDups(formName, field, pages);
361                                 if (error != null)
362                                 {
363                                     throw new SAXException JavaDoc(error);
364                                 }
365                             }
366                         }
367                     } // ignore any child that is not a 'page'
368
}
369                 // sanity check number of pages
370
if (pages.size() < 1)
371                 {
372                     throw new ServletException JavaDoc("Form " + formName + " has no pages");
373                 }
374                 int maxPages = SubmitServlet.EDIT_METADATA_2 - SubmitServlet.EDIT_METADATA_1 + 1;
375                 if ( pages.size() > maxPages)
376                 {
377                     throw new ServletException JavaDoc("Form " + formName + " exceeds maximum pages: " + maxPages);
378                 }
379             }
380         }
381         if (numForms == 0)
382         {
383             throw new ServletException JavaDoc("No form definition found");
384         }
385     }
386
387     /**
388      * Process parts of a field
389      * At the end, make sure that input-types 'qualdrop_value' and
390      * 'twobox' are marked repeatable. Complain if dc-element, label,
391      * or input-type are missing.
392      */

393     private void processPageParts(String JavaDoc formName, String JavaDoc page, Node n, HashMap JavaDoc field)
394         throws SAXException JavaDoc
395     {
396         NodeList nl = n.getChildNodes();
397         int len = nl.getLength();
398         for (int i = 0; i < len; i++)
399         {
400             Node nd = nl.item(i);
401             if ( ! isEmptyTextNode(nd) )
402             {
403                 String JavaDoc tagName = nd.getNodeName();
404                 String JavaDoc value = getValue(nd);
405                 field.put(tagName, value);
406                 if (tagName.equals("input-type"))
407                 {
408                     if (value.equals("dropdown") || value.equals("qualdrop_value"))
409                     {
410                         String JavaDoc pairTypeName = getAttribute(nd, PAIR_TYPE_NAME);
411                         if (pairTypeName == null)
412                         {
413                             throw new SAXException JavaDoc("Form " + formName + ", field " +
414                                                     field.get("dc-element") +
415                                                     "." + field.get("dc-qualifier") +
416                                                     " has no name attribute");
417                         }
418                         else
419                         {
420                             field.put(PAIR_TYPE_NAME, pairTypeName);
421                         }
422                     }
423                 }
424             }
425         }
426         String JavaDoc missing = null;
427         if (field.get("dc-element") == null)
428         {
429             missing = "dc-element";
430         }
431         if (field.get("label") == null)
432         {
433             missing = "label";
434         }
435         if (field.get("input-type") == null)
436         {
437             missing = "input-type";
438         }
439         if ( missing != null )
440         {
441             String JavaDoc msg = "Required field " + missing + " missing on page " + page + " of form " + formName;
442             throw new SAXException JavaDoc(msg);
443         }
444         String JavaDoc type = (String JavaDoc)field.get("input-type");
445         if (type.equals("twobox") || type.equals("qualdrop_value"))
446         {
447             String JavaDoc rpt = (String JavaDoc)field.get("repeatable");
448             if ((rpt == null) ||
449                     ((!rpt.equalsIgnoreCase("yes")) &&
450                             (!rpt.equalsIgnoreCase("true"))))
451             {
452                 String JavaDoc msg = "The field \'"+field.get("label")+"\' must be repeatable";
453                 throw new SAXException JavaDoc(msg);
454             }
455         }
456     }
457
458     /**
459      * Check that this is the only field with the name dc-element.dc-qualifier
460      * If there is a duplicate, return an error message, else return null;
461      */

462     private String JavaDoc checkForDups(String JavaDoc formName, HashMap JavaDoc field, Vector JavaDoc pages)
463     {
464         int matches = 0;
465         String JavaDoc err = null;
466         String JavaDoc schema = (String JavaDoc)field.get("dc-schema");
467         String JavaDoc elem = (String JavaDoc)field.get("dc-element");
468         String JavaDoc qual = (String JavaDoc)field.get("dc-qualifier");
469         if ((schema == null) || (schema.equals("")))
470         {
471             schema = MetadataSchema.DC_SCHEMA;
472         }
473         String JavaDoc schemaTest;
474         
475         for (int i = 0; i < pages.size(); i++)
476         {
477             Vector JavaDoc pg = (Vector JavaDoc)pages.get(i);
478             for (int j = 0; j < pg.size(); j++)
479             {
480                 HashMap JavaDoc fld = (HashMap JavaDoc)pg.get(j);
481                 if ((fld.get("dc-schema") == null) ||
482                     (((String JavaDoc)fld.get("dc-schema")).equals("")))
483                 {
484                     schemaTest = MetadataSchema.DC_SCHEMA;
485                 }
486                 else
487                 {
488                     schemaTest = (String JavaDoc)fld.get("dc-schema");
489                 }
490                 
491                 // Are the schema and element the same? If so, check the qualifier
492
if ((((String JavaDoc)fld.get("dc-element")).equals(elem)) &&
493                     (schemaTest.equals(schema)))
494                 {
495                     String JavaDoc ql = (String JavaDoc)fld.get("dc-qualifier");
496                     if (qual != null)
497                     {
498                         if ((ql != null) && ql.equals(qual))
499                         {
500                             matches++;
501                         }
502                     }
503                     else if (ql == null)
504                     {
505                         matches++;
506                     }
507                 }
508             }
509         }
510         if (matches > 1)
511         {
512             err = "Duplicate field " + schema + "." + elem + "." + qual + " detected in form " + formName;
513         }
514         
515         return err;
516     }
517
518
519     /**
520      * Process the form-value-pairs section of the XML file.
521      * Each element is formed thusly:
522      * <value-pairs name="..." dc-term="...">
523      * <pair>
524      * <display>displayed name-</display>
525      * <storage>stored name</storage>
526      * </pair>
527      * For each value-pairs element, create a new vector, and extract all
528      * the pairs contained within it. Put the display and storage values,
529      * respectively, in the next slots in the vector. Store the vector
530      * in the passed in hashmap.
531      */

532     private void processValuePairs(Node e)
533         throws SAXException JavaDoc
534     {
535         NodeList nl = e.getChildNodes();
536         int len = nl.getLength();
537         for (int i = 0; i < len; i++)
538         {
539             Node nd = nl.item(i);
540             String JavaDoc tagName = nd.getNodeName();
541
542             // process each value-pairs set
543
if (tagName.equals("value-pairs"))
544             {
545                 String JavaDoc pairsName = getAttribute(nd, PAIR_TYPE_NAME);
546                 String JavaDoc dcTerm = getAttribute(nd, "dc-term");
547                 if (pairsName == null)
548                 {
549                     String JavaDoc errString =
550                         "Missing name attribute for value-pairs for DC term " + dcTerm;
551                     throw new SAXException JavaDoc(errString);
552
553                 }
554                 Vector JavaDoc pairs = new Vector JavaDoc();
555                 valuePairs.put(pairsName, pairs);
556                 NodeList cl = nd.getChildNodes();
557                 int lench = cl.getLength();
558                 for (int j = 0; j < lench; j++)
559                 {
560                     Node nch = cl.item(j);
561                     String JavaDoc display = null;
562                     String JavaDoc storage = null;
563
564                     if (nch.getNodeName().equals("pair"))
565                     {
566                         NodeList pl = nch.getChildNodes();
567                         int plen = pl.getLength();
568                         for (int k = 0; k < plen; k++)
569                         {
570                             Node vn= pl.item(k);
571                             String JavaDoc vName = vn.getNodeName();
572                             if (vName.equals("displayed-value"))
573                             {
574                                 display = getValue(vn);
575                             }
576                             else if (vName.equals("stored-value"))
577                             {
578                                 storage = getValue(vn);
579                                 if (storage == null)
580                                 {
581                                     storage = "";
582                                 }
583                             } // ignore any children that aren't 'display' or 'storage'
584
}
585                         pairs.add(display);
586                         pairs.add(storage);
587                     } // ignore any children that aren't a 'pair'
588
}
589             } // ignore any children that aren't a 'value-pair'
590
}
591     }
592
593
594     /**
595      * Check that all referenced value-pairs are present
596      * and field is consistent
597      *
598      * Throws ServletException if detects a missing value-pair.
599      */

600
601     private void checkValues()
602         throws ServletException JavaDoc
603     {
604         // Step through every field of every page of every form
605
Iterator JavaDoc ki = formDefns.keySet().iterator();
606         while (ki.hasNext())
607         {
608             String JavaDoc idName = (String JavaDoc)ki.next();
609             Vector JavaDoc pages = (Vector JavaDoc)formDefns.get(idName);
610             for (int i = 0; i < pages.size(); i++)
611             {
612                 Vector JavaDoc page = (Vector JavaDoc)pages.get(i);
613                 for (int j = 0; j < page.size(); j++)
614                 {
615                     HashMap JavaDoc fld = (HashMap JavaDoc)page.get(j);
616                     // verify reference in certain input types
617
String JavaDoc type = (String JavaDoc)fld.get("input-type");
618                     if (type.equals("dropdown") || type.equals("qualdrop_value"))
619                     {
620                         String JavaDoc pairsName = (String JavaDoc)fld.get(PAIR_TYPE_NAME);
621                         Vector JavaDoc v = (Vector JavaDoc)valuePairs.get(pairsName);
622                         if (v == null)
623                         {
624                             String JavaDoc errString = "Cannot find value pairs for " + pairsName;
625                             throw new ServletException JavaDoc(errString);
626                         }
627                     }
628                     // if visibility restricted, make sure field is not required
629
String JavaDoc visibility = (String JavaDoc)fld.get("visibility");
630                     if (visibility != null && visibility.length() > 0 )
631                     {
632                         String JavaDoc required = (String JavaDoc)fld.get("required");
633                         if (required != null && required.length() > 0)
634                         {
635                             String JavaDoc errString = "Field '" + (String JavaDoc)fld.get("label") +
636                                             "' is required but invisible";
637                             throw new ServletException JavaDoc(errString);
638                         }
639                     }
640                 }
641             }
642         }
643     }
644     
645     private Node getElement(Node nd)
646     {
647         NodeList nl = nd.getChildNodes();
648         int len = nl.getLength();
649         for (int i = 0; i < len; i++)
650         {
651             Node n = nl.item(i);
652             if (n.getNodeType() == Node.ELEMENT_NODE)
653             {
654                 return n;
655             }
656         }
657         return null;
658      }
659
660     private boolean isEmptyTextNode(Node nd)
661     {
662         boolean isEmpty = false;
663         if (nd.getNodeType() == Node.TEXT_NODE)
664         {
665             String JavaDoc text = nd.getNodeValue().trim();
666             if (text.length() == 0)
667             {
668                 isEmpty = true;
669             }
670         }
671         return isEmpty;
672     }
673
674     /**
675      * Returns the value of the node's attribute named <name>
676      */

677     private String JavaDoc getAttribute(Node e, String JavaDoc name)
678     {
679         NamedNodeMap attrs = e.getAttributes();
680         int len = attrs.getLength();
681         if (len > 0)
682         {
683             int i;
684             for (i = 0; i < len; i++)
685             {
686                 Node attr = attrs.item(i);
687                 if (name.equals(attr.getNodeName()))
688                 {
689                     return attr.getNodeValue().trim();
690                 }
691             }
692         }
693         //no such attribute
694
return null;
695     }
696
697     /**
698      * Returns the value found in the Text node (if any) in the
699      * node list that's passed in.
700      */

701     private String JavaDoc getValue(Node nd)
702     {
703         NodeList nl = nd.getChildNodes();
704         int len = nl.getLength();
705         for (int i = 0; i < len; i++)
706         {
707             Node n = nl.item(i);
708             short type = n.getNodeType();
709             if (type == Node.TEXT_NODE)
710             {
711                 return n.getNodeValue().trim();
712             }
713         }
714         // Didn't find a text node
715
return null;
716     }
717 }
718
Popular Tags