Home | History | Annotate | Download | only in kdom
      1 /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
      2  *
      3  * Permission is hereby granted, free of charge, to any person obtaining a copy
      4  * of this software and associated documentation files (the "Software"), to deal
      5  * in the Software without restriction, including without limitation the rights
      6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
      7  * sell copies of the Software, and to permit persons to whom the Software is
      8  * furnished to do so, subject to the following conditions:
      9  *
     10  * The  above copyright notice and this permission notice shall be included in
     11  * all copies or substantial portions of the Software.
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     19  * IN THE SOFTWARE. */
     20 
     21 package org.kxml2.kdom;
     22 
     23 import java.io.*;
     24 import java.util.*;
     25 
     26 import org.xmlpull.v1.*;
     27 
     28 /**
     29  * In order to create an element, please use the createElement method
     30  * instead of invoking the constructor directly. The right place to
     31  * add user defined initialization code is the init method. */
     32 
     33 public class Element extends Node {
     34 
     35     protected String namespace;
     36     protected String name;
     37     protected Vector attributes;
     38     protected Node parent;
     39     protected Vector prefixes;
     40 
     41     public Element() {
     42     }
     43 
     44     /**
     45      * called when all properties are set, but before children
     46      * are parsed. Please do not use setParent for initialization
     47      * code any longer. */
     48 
     49     public void init() {
     50     }
     51 
     52 
     53 
     54 
     55     /**
     56      * removes all children and attributes */
     57 
     58     public void clear() {
     59         attributes = null;
     60         children = null;
     61     }
     62 
     63     /**
     64      * Forwards creation request to parent if any, otherwise
     65      * calls super.createElement. */
     66 
     67     public Element createElement(
     68         String namespace,
     69         String name) {
     70 
     71         return (this.parent == null)
     72             ? super.createElement(namespace, name)
     73             : this.parent.createElement(namespace, name);
     74     }
     75 
     76     /**
     77      * Returns the number of attributes of this element. */
     78 
     79     public int getAttributeCount() {
     80         return attributes == null ? 0 : attributes.size();
     81     }
     82 
     83     public String getAttributeNamespace (int index) {
     84         return ((String []) attributes.elementAt (index)) [0];
     85     }
     86 
     87 /*    public String getAttributePrefix (int index) {
     88         return ((String []) attributes.elementAt (index)) [1];
     89     }*/
     90 
     91     public String getAttributeName (int index) {
     92         return ((String []) attributes.elementAt (index)) [1];
     93     }
     94 
     95 
     96     public String getAttributeValue (int index) {
     97         return ((String []) attributes.elementAt (index)) [2];
     98     }
     99 
    100 
    101     public String getAttributeValue (String namespace, String name) {
    102         for (int i = 0; i < getAttributeCount (); i++) {
    103             if (name.equals (getAttributeName (i))
    104                 && (namespace == null || namespace.equals (getAttributeNamespace(i)))) {
    105                 return getAttributeValue (i);
    106             }
    107         }
    108         return null;
    109     }
    110 
    111     /**
    112      * Returns the root node, determined by ascending to the
    113      * all parents un of the root element. */
    114 
    115     public Node getRoot() {
    116 
    117         Element current = this;
    118 
    119         while (current.parent != null) {
    120             if (!(current.parent instanceof Element)) return current.parent;
    121             current = (Element) current.parent;
    122         }
    123 
    124         return current;
    125     }
    126 
    127     /**
    128      * returns the (local) name of the element */
    129 
    130     public String getName() {
    131         return name;
    132     }
    133 
    134     /**
    135      * returns the namespace of the element */
    136 
    137     public String getNamespace() {
    138         return namespace;
    139     }
    140 
    141 
    142     /**
    143      * returns the namespace for the given prefix */
    144 
    145     public String getNamespaceUri (String prefix) {
    146         int cnt = getNamespaceCount ();
    147         for (int i = 0; i < cnt; i++) {
    148             if (prefix == getNamespacePrefix (i) ||
    149                 (prefix != null && prefix.equals (getNamespacePrefix (i))))
    150                 return getNamespaceUri (i);
    151         }
    152         return parent instanceof Element ? ((Element) parent).getNamespaceUri (prefix) : null;
    153     }
    154 
    155 
    156     /**
    157      * returns the number of declared namespaces, NOT including
    158      * parent elements */
    159 
    160     public int getNamespaceCount () {
    161         return (prefixes == null ? 0 : prefixes.size ());
    162     }
    163 
    164 
    165     public String getNamespacePrefix (int i) {
    166         return ((String []) prefixes.elementAt (i)) [0];
    167     }
    168 
    169     public String getNamespaceUri (int i) {
    170         return ((String []) prefixes.elementAt (i)) [1];
    171     }
    172 
    173 
    174     /**
    175      * Returns the parent node of this element */
    176 
    177     public Node getParent() {
    178         return parent;
    179     }
    180 
    181     /*
    182      * Returns the parent element if available, null otherwise
    183 
    184     public Element getParentElement() {
    185         return (parent instanceof Element)
    186             ? ((Element) parent)
    187             : null;
    188     }
    189 */
    190 
    191     /**
    192      * Builds the child elements from the given Parser. By overwriting
    193      * parse, an element can take complete control over parsing its
    194      * subtree. */
    195 
    196     public void parse(XmlPullParser parser)
    197         throws IOException, XmlPullParserException {
    198 
    199         for (int i = parser.getNamespaceCount (parser.getDepth () - 1);
    200             i < parser.getNamespaceCount (parser.getDepth ()); i++) {
    201             setPrefix (parser.getNamespacePrefix (i), parser.getNamespaceUri(i));
    202         }
    203 
    204 
    205         for (int i = 0; i < parser.getAttributeCount (); i++)
    206             setAttribute (parser.getAttributeNamespace (i),
    207 //                          parser.getAttributePrefix (i),
    208                           parser.getAttributeName (i),
    209                           parser.getAttributeValue (i));
    210 
    211 
    212         //        if (prefixMap == null) throw new RuntimeException ("!!");
    213 
    214         init();
    215 
    216 
    217         if (parser.isEmptyElementTag())
    218             parser.nextToken ();
    219         else {
    220             parser.nextToken ();
    221             super.parse(parser);
    222 
    223             if (getChildCount() == 0)
    224                 addChild(IGNORABLE_WHITESPACE, "");
    225         }
    226 
    227         parser.require(
    228             XmlPullParser.END_TAG,
    229             getNamespace(),
    230             getName());
    231 
    232         parser.nextToken ();
    233     }
    234 
    235 
    236     /**
    237      * Sets the given attribute; a value of null removes the attribute */
    238 
    239     public void setAttribute (String namespace, String name, String value) {
    240         if (attributes == null)
    241             attributes = new Vector ();
    242 
    243         if (namespace == null)
    244             namespace = "";
    245 
    246         for (int i = attributes.size()-1; i >=0; i--){
    247             String[] attribut = (String[]) attributes.elementAt(i);
    248             if (attribut[0].equals(namespace) &&
    249                 attribut[1].equals(name)){
    250 
    251                 if (value == null) {
    252                     attributes.removeElementAt(i);
    253                 }
    254                 else {
    255                     attribut[2] = value;
    256                 }
    257                 return;
    258             }
    259         }
    260 
    261         attributes.addElement
    262             (new String [] {namespace, name, value});
    263     }
    264 
    265 
    266     /**
    267      * Sets the given prefix; a namespace value of null removess the
    268      * prefix */
    269 
    270     public void setPrefix (String prefix, String namespace) {
    271         if (prefixes == null) prefixes = new Vector ();
    272         prefixes.addElement (new String [] {prefix, namespace});
    273     }
    274 
    275 
    276     /**
    277      * sets the name of the element */
    278 
    279     public void setName(String name) {
    280         this.name = name;
    281     }
    282 
    283     /**
    284      * sets the namespace of the element. Please note: For no
    285      * namespace, please use Xml.NO_NAMESPACE, null is not a legal
    286      * value. Currently, null is converted to Xml.NO_NAMESPACE, but
    287      * future versions may throw an exception. */
    288 
    289     public void setNamespace(String namespace) {
    290         if (namespace == null)
    291             throw new NullPointerException ("Use \"\" for empty namespace");
    292         this.namespace = namespace;
    293     }
    294 
    295     /**
    296      * Sets the Parent of this element. Automatically called from the
    297      * add method.  Please use with care, you can simply
    298      * create inconsitencies in the document tree structure using
    299      * this method!  */
    300 
    301     protected void setParent(Node parent) {
    302         this.parent = parent;
    303     }
    304 
    305 
    306     /**
    307      * Writes this element and all children to the given XmlWriter. */
    308 
    309     public void write(XmlSerializer writer)
    310         throws IOException {
    311 
    312         if (prefixes != null) {
    313             for (int i = 0; i < prefixes.size(); i++) {
    314                 writer.setPrefix (getNamespacePrefix (i), getNamespaceUri (i));
    315             }
    316         }
    317 
    318         writer.startTag(
    319             getNamespace(),
    320             getName());
    321 
    322         int len = getAttributeCount();
    323 
    324         for (int i = 0; i < len; i++) {
    325             writer.attribute(
    326                 getAttributeNamespace(i),
    327                 getAttributeName(i),
    328                 getAttributeValue(i));
    329         }
    330 
    331         writeChildren(writer);
    332 
    333         writer.endTag(getNamespace (), getName ());
    334     }
    335 }
    336