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