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 21package org.ksoap2.kdom; 22 23import java.io.*; 24import java.util.*; 25 26import 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 33public 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 * removes all children and attributes */ 54 55 public void clear() { 56 attributes = null; 57 children = null; 58 } 59 60 /** 61 * Forwards creation request to parent if any, otherwise 62 * calls super.createElement. */ 63 64 public Element createElement( 65 String namespace, 66 String name) { 67 68 return (this.parent == null) 69 ? super.createElement(namespace, name) 70 : this.parent.createElement(namespace, name); 71 } 72 73 /** 74 * Returns the number of attributes of this element. */ 75 76 public int getAttributeCount() { 77 return attributes == null ? 0 : attributes.size(); 78 } 79 80 public String getAttributeNamespace(int index) { 81 return ((String[]) attributes.elementAt(index))[0]; 82 } 83 84 /* public String getAttributePrefix (int index) { 85 return ((String []) attributes.elementAt (index)) [1]; 86 }*/ 87 88 public String getAttributeName(int index) { 89 return ((String[]) attributes.elementAt(index))[1]; 90 } 91 92 public String getAttributeValue(int index) { 93 return ((String[]) attributes.elementAt(index))[2]; 94 } 95 96 public String getAttributeValue(String namespace, String name) { 97 for (int i = 0; i < getAttributeCount(); i++) { 98 if (name.equals(getAttributeName(i)) 99 && (namespace == null || namespace.equals(getAttributeNamespace(i)))) { 100 return getAttributeValue(i); 101 } 102 } 103 return null; 104 } 105 106 /** 107 * Returns the root node, determined by ascending to the 108 * all parents un of the root element. */ 109 110 public Node getRoot() { 111 112 Element current = this; 113 114 while (current.parent != null) { 115 if (!(current.parent instanceof Element)) 116 return current.parent; 117 current = (Element) current.parent; 118 } 119 120 return current; 121 } 122 123 /** 124 * returns the (local) name of the element */ 125 126 public String getName() { 127 return name; 128 } 129 130 /** 131 * returns the namespace of the element */ 132 133 public String getNamespace() { 134 return namespace; 135 } 136 137 /** 138 * returns the namespace for the given prefix */ 139 140 public String getNamespaceUri(String prefix) { 141 int cnt = getNamespaceCount(); 142 for (int i = 0; i < cnt; i++) { 143 if (prefix == getNamespacePrefix(i) || 144 (prefix != null && prefix.equals(getNamespacePrefix(i)))) 145 return getNamespaceUri(i); 146 } 147 return parent instanceof Element ? ((Element) parent).getNamespaceUri(prefix) : null; 148 } 149 150 /** 151 * returns the number of declared namespaces, NOT including 152 * parent elements */ 153 154 public int getNamespaceCount() { 155 return (prefixes == null ? 0 : prefixes.size()); 156 } 157 158 public String getNamespacePrefix(int i) { 159 return ((String[]) prefixes.elementAt(i))[0]; 160 } 161 162 public String getNamespaceUri(int i) { 163 return ((String[]) prefixes.elementAt(i))[1]; 164 } 165 166 /** 167 * Returns the parent node of this element */ 168 169 public Node getParent() { 170 return parent; 171 } 172 173 /* 174 * Returns the parent element if available, null otherwise 175 176 public Element getParentElement() { 177 return (parent instanceof Element) 178 ? ((Element) parent) 179 : null; 180 } 181 */ 182 183 /** 184 * Builds the child elements from the given Parser. By overwriting 185 * parse, an element can take complete control over parsing its 186 * subtree. */ 187 188 public void parse(XmlPullParser parser) 189 throws IOException, XmlPullParserException { 190 191 for (int i = parser.getNamespaceCount(parser.getDepth() - 1); i < parser 192 .getNamespaceCount(parser.getDepth()); i++) { 193 setPrefix(parser.getNamespacePrefix(i), parser.getNamespaceUri(i)); 194 } 195 196 for (int i = 0; i < parser.getAttributeCount(); i++) 197 setAttribute(parser.getAttributeNamespace(i), 198 // parser.getAttributePrefix (i), 199 parser.getAttributeName(i), 200 parser.getAttributeValue(i)); 201 202 // if (prefixMap == null) throw new RuntimeException ("!!"); 203 204 init(); 205 206 if (parser.isEmptyElementTag()) 207 parser.nextToken(); 208 else { 209 parser.nextToken(); 210 super.parse(parser); 211 212 if (getChildCount() == 0) 213 addChild(IGNORABLE_WHITESPACE, ""); 214 } 215 216 parser.require( 217 XmlPullParser.END_TAG, 218 getNamespace(), 219 getName()); 220 221 parser.nextToken(); 222 } 223 224 /** 225 * Sets the given attribute; a value of null removes the attribute */ 226 227 public void setAttribute(String namespace, String name, String value) { 228 if (attributes == null) 229 attributes = new Vector(); 230 231 if (namespace == null) 232 namespace = ""; 233 234 for (int i = attributes.size() - 1; i >= 0; i--) { 235 String[] attribut = (String[]) attributes.elementAt(i); 236 if (attribut[0].equals(namespace) && 237 attribut[1].equals(name)) { 238 239 if (value == null) { 240 attributes.removeElementAt(i); 241 } 242 else { 243 attribut[2] = value; 244 } 245 return; 246 } 247 } 248 249 attributes.addElement 250 (new String[] { 251 namespace, name, value 252 }); 253 } 254 255 /** 256 * Sets the given prefix; a namespace value of null removess the 257 * prefix */ 258 259 public void setPrefix(String prefix, String namespace) { 260 if (prefixes == null) 261 prefixes = new Vector(); 262 prefixes.addElement(new String[] { 263 prefix, namespace 264 }); 265 } 266 267 /** 268 * sets the name of the element */ 269 270 public void setName(String name) { 271 this.name = name; 272 } 273 274 /** 275 * sets the namespace of the element. Please note: For no 276 * namespace, please use Xml.NO_NAMESPACE, null is not a legal 277 * value. Currently, null is converted to Xml.NO_NAMESPACE, but 278 * future versions may throw an exception. */ 279 280 public void setNamespace(String namespace) { 281 if (namespace == null) 282 throw new NullPointerException("Use \"\" for empty namespace"); 283 this.namespace = namespace; 284 } 285 286 /** 287 * Sets the Parent of this element. Automatically called from the 288 * add method. Please use with care, you can simply 289 * create inconsitencies in the document tree structure using 290 * this method! */ 291 292 protected void setParent(Node parent) { 293 this.parent = parent; 294 } 295 296 /** 297 * Writes this element and all children to the given XmlWriter. */ 298 299 public void write(XmlSerializer writer) 300 throws IOException { 301 302 if (prefixes != null) { 303 for (int i = 0; i < prefixes.size(); i++) { 304 writer.setPrefix(getNamespacePrefix(i), getNamespaceUri(i)); 305 } 306 } 307 308 writer.startTag( 309 getNamespace(), 310 getName()); 311 312 int len = getAttributeCount(); 313 314 for (int i = 0; i < len; i++) { 315 writer.attribute( 316 getAttributeNamespace(i), 317 getAttributeName(i), 318 getAttributeValue(i)); 319 } 320 321 writeChildren(writer); 322 323 writer.endTag(getNamespace(), getName()); 324 } 325} 326