KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nu > xom > Element


1 /* Copyright 2002-2005 Elliotte Rusty Harold
2    
3    This library is free software; you can redistribute it and/or modify
4    it under the terms of version 2.1 of the GNU Lesser General Public
5    License as published by the Free Software Foundation.
6    
7    This library is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10    GNU Lesser General Public License for more details.
11    
12    You should have received a copy of the GNU Lesser General Public
13    License along with this library; if not, write to the
14    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15    Boston, MA 02111-1307 USA
16    
17    You can contact Elliotte Rusty Harold by sending e-mail to
18    elharo@metalab.unc.edu. Please include the word "XOM" in the
19    subject line. The XOM home page is located at http://www.xom.nu/
20 */

21
22 package nu.xom;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.NoSuchElementException JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.SortedSet JavaDoc;
30 import java.util.TreeSet JavaDoc;
31
32 /**
33  * <p>
34  * This class represents an XML element. Each
35  * element has the following properties:
36  * </p>
37  *
38  * <ul>
39  * <li>Local name</li>
40  * <li>Prefix (which may be null or the empty string) </li>
41  * <li>Namespace URI (which may be null or the empty string) </li>
42  * <li>A list of attributes</li>
43  * <li>A list of namespace declarations for this element
44  * (not including those inherited from its parent)</li>
45  * <li>A list of child nodes</li>
46  * </ul>
47  *
48  * @author Elliotte Rusty Harold
49  * @version 1.0
50  *
51  */

52 public class Element extends ParentNode {
53
54     private String JavaDoc localName;
55     private String JavaDoc prefix;
56     private String JavaDoc URI;
57
58     private ArrayList JavaDoc attributes = null;
59     private Namespaces namespaces = null;
60
61     /**
62      * <p>
63      * Creates a new element in no namespace.
64      * </p>
65      *
66      * @param name the name of the element
67      *
68      * @throws IllegalNameException if <code>name</code>
69      * is not a legal XML 1.0 non-colonized name
70      */

71     public Element(String JavaDoc name) {
72         this(name, "");
73     }
74
75     
76     /**
77      * <p>
78      * Creates a new element in a namespace.
79      * </p>
80      *
81      * @param name the qualified name of the element
82      * @param uri the namespace URI of the element
83      *
84      * @throws IllegalNameException if <code>name</code>
85      * is not a legal XML 1.0 non-colonized name
86      * @throws NamespaceConflictException if <code>name</code>'s prefix
87      * cannot be used with <code>uri</code>
88      * @throws MalformedURIException if <code>uri</code>
89      * is not an RFC 2396 absolute URI reference
90      */

91     public Element(String JavaDoc name, String JavaDoc uri) {
92         
93         // The shadowing is important here.
94
// I don't want to set the prefix field just yet.
95
String JavaDoc prefix = "";
96         String JavaDoc localName = name;
97         int colon = name.indexOf(':');
98         if (colon > 0) {
99             prefix = name.substring(0, colon);
100             localName = name.substring(colon + 1);
101         }
102         
103         // The order of these next two calls
104
// matters a great deal.
105
_setNamespacePrefix(prefix);
106         _setNamespaceURI(uri);
107         try {
108             _setLocalName(localName);
109         }
110         catch (IllegalNameException ex) {
111             ex.setData(name);
112             throw ex;
113         }
114         
115     }
116
117     
118     private Element() {}
119
120     
121     static Element build(String JavaDoc name, String JavaDoc uri) {
122         
123         Element result = new Element();
124         String JavaDoc prefix = "";
125         String JavaDoc localName = name;
126         int colon = name.indexOf(':');
127         if (colon >= 0) {
128             prefix = name.substring(0, colon);
129             localName = name.substring(colon + 1);
130         }
131         result.prefix = prefix;
132         result.localName = localName;
133         // We do need to verify the URI here because parsers are
134
// allowing relative URIs which XOM forbids, for reasons
135
// of canonical XML if nothing else. But we only have to verify
136
// that it's an absolute base URI. I don't have to verify
137
// no conflicts.
138
if (! "".equals(uri)) Verifier.checkAbsoluteURIReference(uri);
139         result.URI = uri;
140         return result;
141         
142     }
143
144
145     /**
146      * <p>
147      * Creates a deep copy of an element.
148      * The copy is disconnected from the tree, and does not
149      * have a parent.
150      * </p>
151      *
152      * @param element the element to copy
153      *
154      */

155     public Element(Element element) {
156         
157         this.prefix = element.prefix;
158         this.localName = element.localName;
159         this.URI = element.URI;
160         
161         // Attach additional namespaces
162
if (element.namespaces != null) {
163             this.namespaces = element.namespaces.copy();
164         }
165         
166         // Attach clones of attributes
167
if (element.attributes != null) {
168             this.attributes = element.copyAttributes();
169         }
170         
171         this.actualBaseURI = element.findActualBaseURI();
172         
173         copyChildren(element, this);
174         
175     }
176     
177
178     private ArrayList JavaDoc copyAttributes() {
179
180         int size = attributes.size();
181         ArrayList JavaDoc copy = new ArrayList JavaDoc(size);
182         for (int i = 0; i < size; i++) {
183             copy.add(((Attribute) attributes.get(i)).copy());
184         }
185         return copy;
186         
187     }
188     
189     
190     private static Element copyTag(final Element source) {
191         
192         Element result = source.shallowCopy();
193         
194         // Attach additional namespaces
195
if (source.namespaces != null) {
196             result.namespaces = source.namespaces.copy();
197         }
198         
199         // Attach clones of attributes
200
if (source.attributes != null) {
201             result.attributes = source.copyAttributes();
202         }
203         
204         result.actualBaseURI = source.findActualBaseURI();
205         
206         return result;
207         
208     }
209
210
211     private static void copyChildren(final Element sourceElement,
212       Element resultElement) {
213         
214         if (sourceElement.getChildCount() == 0) return;
215         ParentNode resultParent = resultElement;
216         Node sourceCurrent = sourceElement;
217         int index = 0;
218         int[] indexes = new int[10];
219         int top = 0;
220         indexes[0] = 0;
221         
222         // true if processing the element for the 2nd time;
223
// i.e. the element's end-tag
224
boolean endTag = false;
225         
226         while (true) {
227             if (!endTag && sourceCurrent.getChildCount() > 0) {
228                sourceCurrent = sourceCurrent.getChild(0);
229                index = 0;
230                top++;
231                indexes = grow(indexes, top);
232                indexes[top] = 0;
233             }
234             else {
235                 endTag = false;
236                 ParentNode sourceParent = sourceCurrent.getParent();
237                 if (sourceParent.getChildCount() - 1 == index) {
238                     sourceCurrent = sourceParent;
239                     top--;
240                     if (sourceCurrent == sourceElement) break;
241                     // switch parent up
242
resultParent = (Element) resultParent.getParent();
243                     index = indexes[top];
244                     endTag = true;
245                     continue;
246                 }
247                 else {
248                     index++;
249                     indexes[top] = index;
250                     sourceCurrent = sourceParent.getChild(index);
251                 }
252             }
253             
254             if (sourceCurrent.isElement()) {
255                 Element child = copyTag((Element) sourceCurrent);
256                 resultParent.appendChild(child);
257                 if (sourceCurrent.getChildCount() > 0) {
258                     resultParent = child;
259                 }
260             }
261             else {
262                 Node child = sourceCurrent.copy();
263                 resultParent.appendChild(child);
264             }
265             
266         }
267         
268     }
269
270
271     private static int[] grow(int[] indexes, int top) {
272         
273         if (top < indexes.length) return indexes;
274         int[] result = new int[indexes.length*2];
275         System.arraycopy(indexes, 0, result, 0, indexes.length);
276         return result;
277         
278     }
279
280
281     /**
282      * <p>
283      * Returns a list of the child elements of
284      * this element with the specified name in no namespace.
285      * The elements returned are in document order.
286      * </p>
287      *
288      * @param name the name of the elements included in the list
289      *
290      * @return a comatose list containing the child elements of this
291      * element with the specified name
292      */

293     public final Elements getChildElements(String JavaDoc name) {
294         return getChildElements(name, "");
295     }
296
297     
298     /**
299      * <p>
300      * Returns a list of the immediate child elements of this
301      * element with the specified local name and namespace URI.
302      * Passing the empty string or null as the local name
303      * returns all elements in the specified namespace.
304      * Passing null or the empty string as the namespace URI
305      * returns elements with the specified name in no namespace.
306      * The elements returned are in document order.
307      * </p>
308      *
309      * @param localName the name of the elements included in the list
310      * @param namespaceURI the namespace URI of the elements included
311      * in the list
312      *
313      * @return a comatose list containing the child
314      * elements of this element with the specified
315      * name in the specified namespace
316      */

317     public final Elements getChildElements(String JavaDoc localName,
318      String JavaDoc namespaceURI) {
319         
320         if (namespaceURI == null) namespaceURI = "";
321         if (localName == null) localName = "";
322         
323         Elements elements = new Elements();
324         for (int i = 0; i < getChildCount(); i++) {
325             Node child = getChild(i);
326             if (child.isElement()) {
327                 Element element = (Element) child;
328                 if ((localName.equals(element.getLocalName())
329                   || localName.length() == 0)
330                   && namespaceURI.equals(element.getNamespaceURI())) {
331                     elements.add(element);
332                 }
333             }
334         }
335         return elements;
336         
337     }
338
339     
340     /**
341      * <p>
342      * Returns a list of all the child elements
343      * of this element in document order.
344      * </p>
345      *
346      * @return a comatose list containing all
347      * child elements of this element
348      */

349     public final Elements getChildElements() {
350         
351         Elements elements = new Elements();
352         for (int i = 0; i < getChildCount(); i++) {
353             Node child = getChild(i);
354             if (child.isElement()) {
355                 Element element = (Element) child;
356                 elements.add(element);
357             }
358         }
359         return elements;
360         
361     }
362
363     
364     /**
365      * <p>
366      * Returns the first child
367      * element with the specified name in no namespace.
368      * If there is no such element, it returns null.
369      * </p>
370      *
371      * @param name the name of the element to return
372      *
373      * @return the first child element with the specified local name
374      * in no namespace or null if there is no such element
375      */

376     public final Element getFirstChildElement(String JavaDoc name) {
377         return getFirstChildElement(name, "");
378     }
379
380     
381     /**
382      * <p>
383      * Returns the first child
384      * element with the specified local name and namespace URI.
385      * If there is no such element, it returns null.
386      * </p>
387      *
388      * @param localName the local name of the element to return
389      * @param namespaceURI the namespace URI of the element to return
390      *
391      * @return the first child with the specified local name in the
392      * specified namespace, or null if there is no such element
393      */

394     public final Element getFirstChildElement(String JavaDoc localName,
395      String JavaDoc namespaceURI) {
396         
397         for (int i = 0; i < getChildCount(); i++) {
398             Node child = getChild(i);
399             if (child.isElement()) {
400                 Element element = (Element) child;
401                 if (localName.equals(element.getLocalName())
402                   && namespaceURI.equals(element.getNamespaceURI())) {
403                     return element;
404                 }
405             }
406         }
407         return null;
408         
409     }
410
411
412     /**
413      * <p>
414      * Adds an attribute to this element, replacing any existing
415      * attribute with the same local name and namespace URI.
416      * </p>
417      *
418      * @param attribute the attribute to add
419      *
420      * @throws MultipleParentException if the attribute is already
421      * attached to an element
422      * @throws NamespaceConflictException if the attribute's prefix
423      * is mapped to a different namespace URI than the same prefix
424      * is mapped to by this element, another attribute of
425      * this element, or an additional namespace declaration
426      * of this element
427      */

428     public void addAttribute(Attribute attribute) {
429
430         if (attribute.getParent() != null) {
431             throw new MultipleParentException(
432               "Attribute already has a parent");
433         }
434         
435         // check for namespace conflicts
436
String JavaDoc attPrefix = attribute.getNamespacePrefix();
437         if (attPrefix.length() != 0 && !"xml".equals(attPrefix)) {
438             if (prefix.equals(attribute.getNamespacePrefix())
439               && !(getNamespaceURI()
440                .equals(attribute.getNamespaceURI()))) {
441                 throw new NamespaceConflictException("Prefix of "
442                   + attribute.getQualifiedName()
443                   + " conflicts with element prefix " + prefix);
444             }
445             // check for conflicts with additional namespaces
446
if (namespaces != null) {
447                 String JavaDoc existing
448                  = namespaces.getURI(attribute.getNamespacePrefix());
449                 if (existing != null
450                   && !existing.equals(attribute.getNamespaceURI())) {
451                     throw new NamespaceConflictException("Attribute prefix "
452                       + attPrefix
453                       + " conflicts with namespace declaration.");
454                 }
455             }
456             
457         }
458         
459         if (attributes == null) attributes = new ArrayList JavaDoc(1);
460         checkPrefixConflict(attribute);
461         
462         // Is there already an attribute with this local name
463
// and namespace? If so, remove it.
464
Attribute oldAttribute = getAttribute(attribute.getLocalName(),
465           attribute.getNamespaceURI());
466         if (oldAttribute != null) attributes.remove(oldAttribute);
467         
468         attributes.add(attribute);
469         attribute.setParent(this);
470         
471     }
472     
473     
474     void fastAddAttribute(Attribute attribute) {
475         if (attributes == null) attributes = new ArrayList JavaDoc(1);
476         attributes.add(attribute);
477         attribute.setParent(this);
478     }
479
480
481     /**
482      * <p>
483      * Removes an attribute from this element.
484      * </p>
485      *
486      * @param attribute the attribute to remove
487      *
488      * @return the attribute that was removed
489      *
490      * @throws NoSuchAttributeException if this element is not the
491      * parent of attribute
492      *
493      */

494     public Attribute removeAttribute(Attribute attribute) {
495         
496         if (attributes == null) {
497             throw new NoSuchAttributeException(
498               "Tried to remove attribute "
499               + attribute.getQualifiedName()
500               + " from non-parent element");
501         }
502         if (attribute == null) {
503             throw new NullPointerException JavaDoc(
504               "Tried to remove null attribute");
505         }
506         if (attributes.remove(attribute)) {
507             attribute.setParent(null);
508             return attribute;
509         }
510         else {
511             throw new NoSuchAttributeException(
512               "Tried to remove attribute "
513               + attribute.getQualifiedName()
514               + " from non-parent element");
515         }
516         
517     }
518
519
520     /**
521      * <p>
522      * Returns the attribute with the specified name in no namespace,
523      * or null if this element does not have an attribute
524      * with that name in no namespace.
525      * </p>
526      *
527      * @param name the name of the attribute
528      *
529      * @return the attribute of this element with the specified name
530      */

531     public final Attribute getAttribute(String JavaDoc name) {
532         return getAttribute(name, "");
533     }
534
535     
536     /**
537      * <p>
538      * Returns the attribute with the specified name and namespace URI,
539      * or null if this element does not have an attribute
540      * with that name in that namespace.
541      * </p>
542      *
543      * @param localName the local name of the attribute
544      * @param namespaceURI the namespace of the attribute
545      *
546      * @return the attribute of this element
547      * with the specified name and namespace
548      */

549     public final Attribute getAttribute(String JavaDoc localName,
550       String JavaDoc namespaceURI) {
551         
552         if (attributes == null) return null;
553         int size = attributes.size();
554         for (int i = 0; i < size; i++) {
555             Attribute a = (Attribute) attributes.get(i);
556             if (a.getLocalName().equals(localName)
557              && a.getNamespaceURI().equals(namespaceURI)) {
558                 return a;
559             }
560         }
561         
562         return null;
563         
564     }
565
566     
567     /**
568      * <p>
569      * Returns the value of the attribute with the specified
570      * name in no namespace,
571      * or null if this element does not have an attribute
572      * with that name.
573      * </p>
574      *
575      * @param name the name of the attribute
576      *
577      * @return the value of the attribute of this element
578      * with the specified name
579      */

580     public final String JavaDoc getAttributeValue(String JavaDoc name) {
581         return getAttributeValue(name, "");
582     }
583
584     
585     /**
586      *
587      * <p>
588      * Returns the number of attributes of this <code>Element</code>,
589      * not counting namespace declarations.
590      * This is always a non-negative number.
591      * </p>
592      *
593      * @return the number of attributes in the container
594      */

595     public final int getAttributeCount() {
596         if (attributes == null) return 0;
597         return attributes.size();
598     }
599     
600     
601     /**
602      *
603      * <p>
604      * Selects an attribute by index.
605      * The index is purely for convenience and has no particular
606      * meaning. In particular, it is <em>not</em> necessarily the
607      * position of this attribute in the original document from
608      * which this <code>Element</code> object was read.
609      * As with most lists in Java, attributes are numbered
610      * from 0 to one less than the length of the list.
611      * </p>
612      *
613      * <p>
614      * In general, you should not add attributes to or remove
615      * attributes from the list while iterating across it.
616      * Doing so will change the indexes of the other attributes in
617      * the list. it is, however, safe to remove an attribute from
618      * either end of the list (0 or <code>getAttributeCount()-1</code>)
619      * until there are no attributes left.
620      * </p>
621      *
622      * @param index the attribute to return
623      *
624      * @return the index<sup>th</sup> attribute of this element
625      *
626      * @throws IndexOutofBoundsException if the index is negative
627      * or greater than or equal to the number of attributes
628      * of this element
629      *
630      */

631     public final Attribute getAttribute(int index) {
632         
633         if (attributes == null) {
634             throw new IndexOutOfBoundsException JavaDoc(
635               "Element does not have any attributes"
636             );
637         }
638         return (Attribute) attributes.get(index);
639         
640     }
641
642
643     /**
644      * <p>
645      * Returns the value of the attribute with the
646      * specified name and namespace URI,
647      * or null if this element does not have such an attribute.
648      * </p>
649      *
650      * @param localName the name of the attribute
651      * @param namespaceURI the namespace of the attribute
652      *
653      * @return the value of the attribute of this element
654      * with the specified name and namespace
655      */

656     public final String JavaDoc getAttributeValue(String JavaDoc localName,
657                                           String JavaDoc namespaceURI) {
658         
659         Attribute attribute = getAttribute(localName, namespaceURI);
660         if (attribute == null) return null;
661         else return attribute.getValue();
662         
663     }
664     
665     
666     /**
667      * <p>
668      * Returns the local name of this element, not including the
669      * namespace prefix or colon.
670      * </p>
671      *
672      * @return the local name of this element
673      */

674     public final String JavaDoc getLocalName() {
675         return localName;
676     }
677
678     
679     /**
680      * <p>
681      * Returns the complete name of this element, including the
682      * namespace prefix if this element has one.
683      * </p>
684      *
685      * @return the qualified name of this element
686      */

687     public final String JavaDoc getQualifiedName() {
688         if (prefix.length() == 0) return localName;
689         else return prefix + ":" + localName;
690     }
691
692     
693     /**
694      * <p>
695      * Returns the prefix of this element, or the empty string
696      * if this element does not have a prefix.
697      * </p>
698      *
699      * @return the prefix of this element
700      */

701     public final String JavaDoc getNamespacePrefix() {
702         return prefix;
703     }
704
705     
706     /**
707      * <p>
708      * Returns the namespace URI of this element,
709      * or the empty string if this element is not
710      * in a namespace.
711      * </p>
712      *
713      * @return the namespace URI of this element
714      */

715     public final String JavaDoc getNamespaceURI() {
716         return URI;
717     }
718
719     
720     /**
721      * <p>
722      * Returns the namespace URI mapped to the specified
723      * prefix within this element. Returns null if this prefix
724      * is not associated with a URI.
725      * </p>
726      *
727      * @param prefix the namespace prefix whose URI is desired
728      *
729      * @return the namespace URI mapped to <code>prefix</code>
730      */

731     public final String JavaDoc getNamespaceURI(String JavaDoc prefix) {
732         
733         Element current = this;
734         String JavaDoc result = getLocalNamespaceURI(prefix);
735         while (result == null) {
736             ParentNode parent = current.getParent();
737             if (parent == null || parent.isDocument()) break;
738             current = (Element) parent;
739             result = current.getLocalNamespaceURI(prefix);
740         }
741         if (result == null && "".equals(prefix)) result = "";
742         return result;
743
744     }
745
746     
747     String JavaDoc getLocalNamespaceURI(String JavaDoc prefix) {
748         
749         if (prefix.equals(this.prefix)) return this.URI;
750         
751         if ("xml".equals(prefix)) {
752             return "http://www.w3.org/XML/1998/namespace";
753         }
754         // This next line uses the original Namespaces 1.0
755
// specification rules.
756
// Namespaces 1.0 + errata is different
757
if ("xmlns".equals(prefix)) return "";
758         // Look in the additional namespace declarations
759
if (namespaces != null) {
760             String JavaDoc result = namespaces.getURI(prefix);
761             if (result != null) return result;
762         }
763         // Look in the attributes
764
if (prefix.length() != 0 && attributes != null) {
765             for (int i = 0; i < attributes.size(); i++) {
766                 Attribute a = (Attribute) attributes.get(i);
767                 if (a.getNamespacePrefix().equals(prefix)) {
768                     return a.getNamespaceURI();
769                 }
770             }
771         }
772         
773         return null;
774         
775     }
776
777    
778     /**
779      * <p>
780      * Sets the local name of this element.
781      * </p>
782      *
783      * @param localName the new local name
784      *
785      * @throws IllegalNameException if <code>localName</code> is not
786      * a legal, non-colonized name
787      */

788     public void setLocalName(String JavaDoc localName) {
789         _setLocalName(localName);
790     }
791
792
793     private void _setLocalName(String JavaDoc localName) {
794         Verifier.checkNCName(localName);
795         this.localName = localName;
796     }
797
798
799     /**
800      * <p>
801      * Sets the namespace URI of this element.
802      * </p>
803      *
804      * @param uri the new namespace URI
805      *
806      * @throws MalformedURIException if <code>uri</code>
807      * is not an absolute RFC2396 URI reference
808      * @throws NamespaceException if this element has a prefix
809      * and <code>uri</code> is null or the empty string;
810      * or if the element's prefix is shared by an attribute
811      * or additional namespace
812      */

813     public void setNamespaceURI(String JavaDoc uri) {
814         _setNamespaceURI(uri);
815     }
816
817     
818     private void _setNamespaceURI(String JavaDoc uri) {
819         
820         if (uri == null) uri = "";
821         // Next line is needed to avoid unintentional
822
// exceptions below when checking for conflicts
823
if (uri.equals(this.URI)) return;
824         if (uri.length() == 0) { // faster than "".equals(uri)
825
if (prefix.length() != 0) {
826                 throw new NamespaceConflictException(
827                  "Prefixed elements must have namespace URIs."
828                 );
829             }
830         }
831         else Verifier.checkAbsoluteURIReference(uri);
832         // Make sure this doesn't conflict with any local
833
// attribute prefixes or additional namespace declarations
834
// Note that if the prefix equals the prefix, then the
835
// URI must equal the old URI, so the URI can't easily be
836
// changed. (you'd need to detach everything first;
837
// change the URIs, then put it all back together
838
if (namespaces != null) {
839         String JavaDoc result = namespaces.getURI(prefix);
840             if (result != null) {
841                 throw new NamespaceConflictException(
842                   "new URI conflicts with existing prefix"
843                 );
844             }
845         }
846         // Look in the attributes
847
if (uri.length() > 0 && attributes != null) {
848             for (int i = 0; i < attributes.size(); i++) {
849                 Attribute a = (Attribute) attributes.get(i);
850                 String JavaDoc attPrefix = a.getNamespacePrefix();
851                 if (attPrefix.length() == 0) continue;
852                 if (a.getNamespacePrefix().equals(prefix)) {
853                     throw new NamespaceConflictException(
854                       "new element URI " + uri
855                       + " conflicts with attribute "
856                       + a.getQualifiedName()
857                     );
858                 }
859             }
860         }
861
862         if ("http://www.w3.org/XML/1998/namespace".equals(uri)
863           && ! "xml".equals(prefix)) {
864             throw new NamespaceConflictException(
865               "Wrong prefix " + prefix +
866               " for the http://www.w3.org/XML/1998/namespace namespace URI"
867             );
868         }
869         else if ("xml".equals(prefix) &&
870           !"http://www.w3.org/XML/1998/namespace".equals(uri)) {
871             throw new NamespaceConflictException(
872               "Wrong namespace URI " + uri + " for the xml prefix"
873             );
874         }
875         
876         this.URI = uri;
877         
878     }
879
880
881     /**
882      * <p>
883      * Sets the namespace prefix of this element.
884      * You can pass null or the empty string to remove the prefix.
885      * </p>
886      *
887      * @param prefix the new namespace prefix
888      *
889      * @throws IllegalNameException if <code>prefix</code> is
890      * not a legal XML non-colonized name
891      * @throws NamespaceConflictException if <code>prefix</code> is
892      * already in use by an attribute or additional
893      * namespace with a different URI than the element
894      * itself
895      */

896     public void setNamespacePrefix(String JavaDoc prefix) {
897         _setNamespacePrefix(prefix);
898     }
899
900
901     private void _setNamespacePrefix(String JavaDoc prefix) {
902         
903         if (prefix == null) prefix = "";
904         if (prefix.length() != 0) Verifier.checkNCName(prefix);
905
906         // Check how this affects or conflicts with
907
// attribute namespaces and additional
908
// namespace declarations.
909
String JavaDoc uri = getLocalNamespaceURI(prefix);
910         if (uri != null) {
911             if (!uri.equals(this.URI) && !"xml".equals(prefix)) {
912                 throw new NamespaceConflictException(prefix
913                  + " conflicts with existing prefix");
914             }
915         }
916         else if ("".equals(this.URI) && !"".equals(prefix)) {
917             throw new NamespaceConflictException(
918               "Cannot assign prefix to element in no namespace");
919         }
920
921         this.prefix = prefix;
922     &