View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 1999-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: DOM2DTMdefaultNamespaceDeclarationNode.java,v 1.2.4.1 2005/09/15 08:15:11 suresh_emailid Exp $
22   */
23  
24  package com.sun.org.apache.xml.internal.dtm.ref.dom2dtm;
25  
26  import com.sun.org.apache.xml.internal.dtm.DTMException;
27  
28  import org.w3c.dom.Attr;
29  import org.w3c.dom.Document;
30  import org.w3c.dom.Element;
31  import org.w3c.dom.NamedNodeMap;
32  import org.w3c.dom.Node;
33  import org.w3c.dom.NodeList;
34  import org.w3c.dom.TypeInfo;
35  import org.w3c.dom.UserDataHandler;
36  import org.w3c.dom.DOMException;
37  
38  /** This is a kluge to let us shove a declaration for xml: into the
39   * DOM2DTM model.  Basically, it creates a proxy node in DOM space to
40   * carry the additional information. This is _NOT_ a full DOM
41   * implementation, and shouldn't be one since it sits alongside the
42   * DOM rather than becoming part of the DOM model.
43   *
44   * (This used to be an internal class within DOM2DTM. Moved out because
45   * I need to perform an instanceof operation on it to support a temporary
46   * workaround in DTMManagerDefault.)
47   *
48   * %REVIEW% What if the DOM2DTM was built around a DocumentFragment and
49   * there isn't a single root element? I think this fails that case...
50   *
51   * %REVIEW% An alternative solution would be to create the node _only_
52   * in DTM space, but given how DOM2DTM is currently written I think
53   * this is simplest.
54   * */
55  public class DOM2DTMdefaultNamespaceDeclarationNode implements Attr,TypeInfo
56  {
57    final String NOT_SUPPORTED_ERR="Unsupported operation on pseudonode";
58  
59    Element pseudoparent;
60    String prefix,uri,nodename;
61    int handle;
62    DOM2DTMdefaultNamespaceDeclarationNode(Element pseudoparent,String prefix,String uri,int handle)
63    {
64      this.pseudoparent=pseudoparent;
65      this.prefix=prefix;
66      this.uri=uri;
67      this.handle=handle;
68      this.nodename="xmlns:"+prefix;
69    }
70    public String getNodeName() {return nodename;}
71    public String getName() {return nodename;}
72    public String getNamespaceURI() {return "http://www.w3.org/2000/xmlns/";}
73    public String getPrefix() {return prefix;}
74    public String getLocalName() {return prefix;}
75    public String getNodeValue() {return uri;}
76    public String getValue() {return uri;}
77    public Element getOwnerElement() {return pseudoparent;}
78  
79    public boolean isSupported(String feature, String version) {return false;}
80    public boolean hasChildNodes() {return false;}
81    public boolean hasAttributes() {return false;}
82    public Node getParentNode() {return null;}
83    public Node getFirstChild() {return null;}
84    public Node getLastChild() {return null;}
85    public Node getPreviousSibling() {return null;}
86    public Node getNextSibling() {return null;}
87    public boolean getSpecified() {return false;}
88    public void normalize() {return;}
89    public NodeList getChildNodes() {return null;}
90    public NamedNodeMap getAttributes() {return null;}
91    public short getNodeType() {return Node.ATTRIBUTE_NODE;}
92    public void setNodeValue(String value) {throw new DTMException(NOT_SUPPORTED_ERR);}
93    public void setValue(String value) {throw new DTMException(NOT_SUPPORTED_ERR);}
94    public void setPrefix(String value) {throw new DTMException(NOT_SUPPORTED_ERR);}
95    public Node insertBefore(Node a, Node b) {throw new DTMException(NOT_SUPPORTED_ERR);}
96    public Node replaceChild(Node a, Node b) {throw new DTMException(NOT_SUPPORTED_ERR);}
97    public Node appendChild(Node a) {throw new DTMException(NOT_SUPPORTED_ERR);}
98    public Node removeChild(Node a) {throw new DTMException(NOT_SUPPORTED_ERR);}
99    public Document getOwnerDocument() {return pseudoparent.getOwnerDocument();}
100   public Node cloneNode(boolean deep) {throw new DTMException(NOT_SUPPORTED_ERR);}
101 
102     /** Non-DOM method, part of the temporary kluge
103      * %REVIEW% This would be a pruning problem, but since it will always be
104      * added to the root element and we prune on elements, we shouldn't have
105      * to worry.
106      */
107     public int getHandleOfNode()
108     {
109         return handle;
110     }
111 
112     //RAMESH: PENDING=> Add proper implementation for the below DOM L3 additions
113 
114     /**
115      * @see org.w3c.dom.TypeInfo#getTypeName()
116      */
117     public String getTypeName() {return null; }
118 
119     /**
120      * @see org.w3c.dom.TypeInfo#getTypeNamespace()
121      */
122     public String getTypeNamespace() { return null;}
123 
124     /**
125      * @see or.gw3c.dom.TypeInfo#isDerivedFrom(String,String,int)
126      */
127     public boolean isDerivedFrom( String ns, String localName, int derivationMethod ) {
128         return false;
129     }
130 
131     public TypeInfo getSchemaTypeInfo() { return this; }
132 
133     public boolean isId( ) { return false; }
134 
135     /**
136      * Associate an object to a key on this node. The object can later be
137      * retrieved from this node by calling <code>getUserData</code> with the
138      * same key.
139      * @param key The key to associate the object to.
140      * @param data The object to associate to the given key, or
141      *   <code>null</code> to remove any existing association to that key.
142      * @param handler The handler to associate to that key, or
143      *   <code>null</code>.
144      * @return Returns the <code>DOMObject</code> previously associated to
145      *   the given key on this node, or <code>null</code> if there was none.
146      * @since DOM Level 3
147      */
148     public Object setUserData(String key,
149                               Object data,
150                               UserDataHandler handler) {
151         return getOwnerDocument().setUserData( key, data, handler);
152     }
153 
154     /**
155      * Retrieves the object associated to a key on a this node. The object
156      * must first have been set to this node by calling
157      * <code>setUserData</code> with the same key.
158      * @param key The key the object is associated to.
159      * @return Returns the <code>DOMObject</code> associated to the given key
160      *   on this node, or <code>null</code> if there was none.
161      * @since DOM Level 3
162      */
163     public Object getUserData(String key) {
164         return getOwnerDocument().getUserData( key);
165     }
166 
167     /**
168      *  This method returns a specialized object which implements the
169      * specialized APIs of the specified feature and version. The
170      * specialized object may also be obtained by using binding-specific
171      * casting methods but is not necessarily expected to, as discussed in Mixed DOM implementations.
172      * @param feature The name of the feature requested (case-insensitive).
173      * @param version  This is the version number of the feature to test. If
174      *   the version is <code>null</code> or the empty string, supporting
175      *   any version of the feature will cause the method to return an
176      *   object that supports at least one version of the feature.
177      * @return  Returns an object which implements the specialized APIs of
178      *   the specified feature and version, if any, or <code>null</code> if
179      *   there is no object which implements interfaces associated with that
180      *   feature. If the <code>DOMObject</code> returned by this method
181      *   implements the <code>Node</code> interface, it must delegate to the
182      *   primary core <code>Node</code> and not return results inconsistent
183      *   with the primary core <code>Node</code> such as attributes,
184      *   childNodes, etc.
185      * @since DOM Level 3
186      */
187     public Object getFeature(String feature, String version) {
188         // we don't have any alternate node, either this node does the job
189         // or we don't have anything that does
190         return isSupported(feature, version) ? this : null;
191     }
192 
193     /**
194      * Tests whether two nodes are equal.
195      * <br>This method tests for equality of nodes, not sameness (i.e.,
196      * whether the two nodes are references to the same object) which can be
197      * tested with <code>Node.isSameNode</code>. All nodes that are the same
198      * will also be equal, though the reverse may not be true.
199      * <br>Two nodes are equal if and only if the following conditions are
200      * satisfied: The two nodes are of the same type.The following string
201      * attributes are equal: <code>nodeName</code>, <code>localName</code>,
202      * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
203      * , <code>baseURI</code>. This is: they are both <code>null</code>, or
204      * they have the same length and are character for character identical.
205      * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
206      * This is: they are both <code>null</code>, or they have the same
207      * length and for each node that exists in one map there is a node that
208      * exists in the other map and is equal, although not necessarily at the
209      * same index.The <code>childNodes</code> <code>NodeLists</code> are
210      * equal. This is: they are both <code>null</code>, or they have the
211      * same length and contain equal nodes at the same index. This is true
212      * for <code>Attr</code> nodes as for any other type of node. Note that
213      * normalization can affect equality; to avoid this, nodes should be
214      * normalized before being compared.
215      * <br>For two <code>DocumentType</code> nodes to be equal, the following
216      * conditions must also be satisfied: The following string attributes
217      * are equal: <code>publicId</code>, <code>systemId</code>,
218      * <code>internalSubset</code>.The <code>entities</code>
219      * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
220      * <code>NamedNodeMaps</code> are equal.
221      * <br>On the other hand, the following do not affect equality: the
222      * <code>ownerDocument</code> attribute, the <code>specified</code>
223      * attribute for <code>Attr</code> nodes, the
224      * <code>isWhitespaceInElementContent</code> attribute for
225      * <code>Text</code> nodes, as well as any user data or event listeners
226      * registered on the nodes.
227      * @param arg The node to compare equality with.
228      * @param deep If <code>true</code>, recursively compare the subtrees; if
229      *   <code>false</code>, compare only the nodes themselves (and its
230      *   attributes, if it is an <code>Element</code>).
231      * @return If the nodes, and possibly subtrees are equal,
232      *   <code>true</code> otherwise <code>false</code>.
233      * @since DOM Level 3
234      */
235     public boolean isEqualNode(Node arg) {
236         if (arg == this) {
237             return true;
238         }
239         if (arg.getNodeType() != getNodeType()) {
240             return false;
241         }
242         // in theory nodeName can't be null but better be careful
243         // who knows what other implementations may be doing?...
244         if (getNodeName() == null) {
245             if (arg.getNodeName() != null) {
246                 return false;
247             }
248         }
249         else if (!getNodeName().equals(arg.getNodeName())) {
250             return false;
251         }
252 
253         if (getLocalName() == null) {
254             if (arg.getLocalName() != null) {
255                 return false;
256             }
257         }
258         else if (!getLocalName().equals(arg.getLocalName())) {
259             return false;
260         }
261 
262         if (getNamespaceURI() == null) {
263             if (arg.getNamespaceURI() != null) {
264                 return false;
265             }
266         }
267         else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
268             return false;
269         }
270 
271         if (getPrefix() == null) {
272             if (arg.getPrefix() != null) {
273                 return false;
274             }
275         }
276         else if (!getPrefix().equals(arg.getPrefix())) {
277             return false;
278         }
279 
280         if (getNodeValue() == null) {
281             if (arg.getNodeValue() != null) {
282                 return false;
283             }
284         }
285         else if (!getNodeValue().equals(arg.getNodeValue())) {
286             return false;
287         }
288     /*
289         if (getBaseURI() == null) {
290             if (((NodeImpl) arg).getBaseURI() != null) {
291                 return false;
292             }
293         }
294         else if (!getBaseURI().equals(((NodeImpl) arg).getBaseURI())) {
295             return false;
296         }
297 */
298 
299              return true;
300     }
301 
302     /**
303      * DOM Level 3 - Experimental:
304      * Look up the namespace URI associated to the given prefix, starting from this node.
305      * Use lookupNamespaceURI(null) to lookup the default namespace
306      *
307      * @param namespaceURI
308      * @return th URI for the namespace
309      * @since DOM Level 3
310      */
311     public String lookupNamespaceURI(String specifiedPrefix) {
312         short type = this.getNodeType();
313         switch (type) {
314         case Node.ELEMENT_NODE : {
315 
316                 String namespace = this.getNamespaceURI();
317                 String prefix = this.getPrefix();
318                 if (namespace !=null) {
319                     // REVISIT: is it possible that prefix is empty string?
320                     if (specifiedPrefix== null && prefix==specifiedPrefix) {
321                         // looking for default namespace
322                         return namespace;
323                     } else if (prefix != null && prefix.equals(specifiedPrefix)) {
324                         // non default namespace
325                         return namespace;
326                     }
327                 }
328                 if (this.hasAttributes()) {
329                     NamedNodeMap map = this.getAttributes();
330                     int length = map.getLength();
331                     for (int i=0;i<length;i++) {
332                         Node attr = map.item(i);
333                         String attrPrefix = attr.getPrefix();
334                         String value = attr.getNodeValue();
335                         namespace = attr.getNamespaceURI();
336                         if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
337                             // at this point we are dealing with DOM Level 2 nodes only
338                             if (specifiedPrefix == null &&
339                                 attr.getNodeName().equals("xmlns")) {
340                                 // default namespace
341                                 return value;
342                             } else if (attrPrefix !=null &&
343                                        attrPrefix.equals("xmlns") &&
344                                        attr.getLocalName().equals(specifiedPrefix)) {
345                  // non default namespace
346                                 return value;
347                             }
348                         }
349                     }
350                 }
351                 /*
352                 NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
353                 if (ancestor != null) {
354                     return ancestor.lookupNamespaceURI(specifiedPrefix);
355                 }
356                 */
357 
358                 return null;
359 
360 
361             }
362 /*
363         case Node.DOCUMENT_NODE : {
364                 return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix) ;
365             }
366 */
367         case Node.ENTITY_NODE :
368         case Node.NOTATION_NODE:
369         case Node.DOCUMENT_FRAGMENT_NODE:
370         case Node.DOCUMENT_TYPE_NODE:
371             // type is unknown
372             return null;
373         case Node.ATTRIBUTE_NODE:{
374                 if (this.getOwnerElement().getNodeType() == Node.ELEMENT_NODE) {
375                     return getOwnerElement().lookupNamespaceURI(specifiedPrefix);
376 
377                 }
378                 return null;
379             }
380         default:{
381            /*
382                 NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
383                 if (ancestor != null) {
384                     return ancestor.lookupNamespaceURI(specifiedPrefix);
385                 }
386              */
387                 return null;
388             }
389 
390         }
391     }
392 
393     /**
394      *  DOM Level 3: Experimental
395      *  This method checks if the specified <code>namespaceURI</code> is the
396      *  default namespace or not.
397      *  @param namespaceURI The namespace URI to look for.
398      *  @return  <code>true</code> if the specified <code>namespaceURI</code>
399      *   is the default namespace, <code>false</code> otherwise.
400      * @since DOM Level 3
401      */
402     public boolean isDefaultNamespace(String namespaceURI){
403        /*
404         // REVISIT: remove casts when DOM L3 becomes REC.
405         short type = this.getNodeType();
406         switch (type) {
407         case Node.ELEMENT_NODE: {
408             String namespace = this.getNamespaceURI();
409             String prefix = this.getPrefix();
410 
411             // REVISIT: is it possible that prefix is empty string?
412             if (prefix == null || prefix.length() == 0) {
413                 if (namespaceURI == null) {
414                     return (namespace == namespaceURI);
415                 }
416                 return namespaceURI.equals(namespace);
417             }
418             if (this.hasAttributes()) {
419                 ElementImpl elem = (ElementImpl)this;
420                 NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
421                 if (attr != null) {
422                     String value = attr.getNodeValue();
423                     if (namespaceURI == null) {
424                         return (namespace == value);
425                     }
426                     return namespaceURI.equals(value);
427                 }
428             }
429 
430             NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
431             if (ancestor != null) {
432                 return ancestor.isDefaultNamespace(namespaceURI);
433             }
434             return false;
435         }
436         case Node.DOCUMENT_NODE:{
437                 return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
438             }
439 
440         case Node.ENTITY_NODE :
441           case Node.NOTATION_NODE:
442         case Node.DOCUMENT_FRAGMENT_NODE:
443         case Node.DOCUMENT_TYPE_NODE:
444             // type is unknown
445             return false;
446         case Node.ATTRIBUTE_NODE:{
447                 if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
448                     return ownerNode.isDefaultNamespace(namespaceURI);
449 
450                 }
451                 return false;
452             }
453         default:{
454                 NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
455                 if (ancestor != null) {
456                     return ancestor.isDefaultNamespace(namespaceURI);
457                 }
458                 return false;
459             }
460 
461         }
462 */
463         return false;
464 
465 
466     }
467 
468     /**
469      *
470      * DOM Level 3 - Experimental:
471      * Look up the prefix associated to the given namespace URI, starting from this node.
472      *
473      * @param namespaceURI
474      * @return the prefix for the namespace
475      */
476     public String lookupPrefix(String namespaceURI){
477 
478         // REVISIT: When Namespaces 1.1 comes out this may not be true
479         // Prefix can't be bound to null namespace
480         if (namespaceURI == null) {
481             return null;
482         }
483 
484         short type = this.getNodeType();
485 
486         switch (type) {
487 /*
488         case Node.ELEMENT_NODE: {
489 
490                 String namespace = this.getNamespaceURI(); // to flip out children
491                 return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
492             }
493 
494         case Node.DOCUMENT_NODE:{
495                 return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
496             }
497 */
498         case Node.ENTITY_NODE :
499         case Node.NOTATION_NODE:
500         case Node.DOCUMENT_FRAGMENT_NODE:
501         case Node.DOCUMENT_TYPE_NODE:
502             // type is unknown
503             return null;
504         case Node.ATTRIBUTE_NODE:{
505                 if (this.getOwnerElement().getNodeType() == Node.ELEMENT_NODE) {
506                     return getOwnerElement().lookupPrefix(namespaceURI);
507 
508                 }
509                 return null;
510             }
511         default:{
512 /*
513                 NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
514                 if (ancestor != null) {
515                     return ancestor.lookupPrefix(namespaceURI);
516                 }
517 */
518                 return null;
519             }
520          }
521     }
522 
523     /**
524      * Returns whether this node is the same node as the given one.
525      * <br>This method provides a way to determine whether two
526      * <code>Node</code> references returned by the implementation reference
527      * the same object. When two <code>Node</code> references are references
528      * to the same object, even if through a proxy, the references may be
529      * used completely interchangably, such that all attributes have the
530      * same values and calling the same DOM method on either reference
531      * always has exactly the same effect.
532      * @param other The node to test against.
533      * @return Returns <code>true</code> if the nodes are the same,
534      *   <code>false</code> otherwise.
535      * @since DOM Level 3
536      */
537     public boolean isSameNode(Node other) {
538         // we do not use any wrapper so the answer is obvious
539         return this == other;
540     }
541 
542     /**
543      * This attribute returns the text content of this node and its
544      * descendants. When it is defined to be null, setting it has no effect.
545      * When set, any possible children this node may have are removed and
546      * replaced by a single <code>Text</code> node containing the string
547      * this attribute is set to. On getting, no serialization is performed,
548      * the returned string does not contain any markup. No whitespace
549      * normalization is performed, the returned string does not contain the
550      * element content whitespaces . Similarly, on setting, no parsing is
551      * performed either, the input string is taken as pure textual content.
552      * <br>The string returned is made of the text content of this node
553      * depending on its type, as defined below:
554      * <table border='1'>
555      * <tr>
556      * <th>Node type</th>
557      * <th>Content</th>
558      * </tr>
559      * <tr>
560      * <td valign='top' rowspan='1' colspan='1'>
561      * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
562      * DOCUMENT_FRAGMENT_NODE</td>
563      * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
564      * attribute value of every child node, excluding COMMENT_NODE and
565      * PROCESSING_INSTRUCTION_NODE nodes</td>
566      * </tr>
567      * <tr>
568      * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
569      * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
570      * <td valign='top' rowspan='1' colspan='1'>
571      * <code>nodeValue</code></td>
572      * </tr>
573      * <tr>
574      * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
575      * <td valign='top' rowspan='1' colspan='1'>
576      * null</td>
577      * </tr>
578      * </table>
579      * @exception DOMException
580      *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
581      * @exception DOMException
582      *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
583      *   fit in a <code>DOMString</code> variable on the implementation
584      *   platform.
585      * @since DOM Level 3
586      */
587     public void setTextContent(String textContent)
588         throws DOMException {
589         setNodeValue(textContent);
590     }
591 
592     /**
593      * This attribute returns the text content of this node and its
594      * descendants. When it is defined to be null, setting it has no effect.
595      * When set, any possible children this node may have are removed and
596      * replaced by a single <code>Text</code> node containing the string
597      * this attribute is set to. On getting, no serialization is performed,
598      * the returned string does not contain any markup. No whitespace
599      * normalization is performed, the returned string does not contain the
600      * element content whitespaces . Similarly, on setting, no parsing is
601      * performed either, the input string is taken as pure textual content.
602      * <br>The string returned is made of the text content of this node
603      * depending on its type, as defined below:
604      * <table border='1'>
605      * <tr>
606      * <th>Node type</th>
607      * <th>Content</th>
608      * </tr>
609      * <tr>
610      * <td valign='top' rowspan='1' colspan='1'>
611      * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
612      * DOCUMENT_FRAGMENT_NODE</td>
613      * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
614      * attribute value of every child node, excluding COMMENT_NODE and
615      * PROCESSING_INSTRUCTION_NODE nodes</td>
616      * </tr>
617      * <tr>
618      * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
619      * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
620      * <td valign='top' rowspan='1' colspan='1'>
621      * <code>nodeValue</code></td>
622      * </tr>
623      * <tr>
624      * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
625      * <td valign='top' rowspan='1' colspan='1'>
626      * null</td>
627      * </tr>
628      * </table>
629      * @exception DOMException
630      *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
631      * @exception DOMException
632      *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
633      *   fit in a <code>DOMString</code> variable on the implementation
634      *   platform.
635      * @since DOM Level 3
636      */
637     public String getTextContent() throws DOMException {
638         return getNodeValue();  // overriden in some subclasses
639     }
640 
641     /**
642      * Compares a node with this node with regard to their position in the
643      * document.
644      * @param other The node to compare against this node.
645      * @return Returns how the given node is positioned relatively to this
646      *   node.
647      * @since DOM Level 3
648      */
649     public short compareDocumentPosition(Node other) throws DOMException {
650         return 0;
651     }
652 
653     /**
654      * The absolute base URI of this node or <code>null</code> if undefined.
655      * This value is computed according to . However, when the
656      * <code>Document</code> supports the feature "HTML" , the base URI is
657      * computed using first the value of the href attribute of the HTML BASE
658      * element if any, and the value of the <code>documentURI</code>
659      * attribute from the <code>Document</code> interface otherwise.
660      * <br> When the node is an <code>Element</code>, a <code>Document</code>
661      * or a a <code>ProcessingInstruction</code>, this attribute represents
662      * the properties [base URI] defined in . When the node is a
663      * <code>Notation</code>, an <code>Entity</code>, or an
664      * <code>EntityReference</code>, this attribute represents the
665      * properties [declaration base URI] in the . How will this be affected
666      * by resolution of relative namespace URIs issue?It's not.Should this
667      * only be on Document, Element, ProcessingInstruction, Entity, and
668      * Notation nodes, according to the infoset? If not, what is it equal to
669      * on other nodes? Null? An empty string? I think it should be the
670      * parent's.No.Should this be read-only and computed or and actual
671      * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
672      * teleconference 30 May 2001).If the base HTML element is not yet
673      * attached to a document, does the insert change the Document.baseURI?
674      * Yes. (F2F 26 Sep 2001)
675      * @since DOM Level 3
676      */
677     public String getBaseURI() {
678         return null;
679     }
680 }