Mercurial > repos > pfrommolt > ngsrich
comparison NGSrich_0.5.5/src/org/jdom/Element.java @ 0:89ad0a9cca52 default tip
Uploaded
| author | pfrommolt |
|---|---|
| date | Mon, 21 Nov 2011 08:12:19 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:89ad0a9cca52 |
|---|---|
| 1 /*-- | |
| 2 | |
| 3 $Id: Element.java,v 1.159 2007/11/14 05:02:08 jhunter Exp $ | |
| 4 | |
| 5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin. | |
| 6 All rights reserved. | |
| 7 | |
| 8 Redistribution and use in source and binary forms, with or without | |
| 9 modification, are permitted provided that the following conditions | |
| 10 are met: | |
| 11 | |
| 12 1. Redistributions of source code must retain the above copyright | |
| 13 notice, this list of conditions, and the following disclaimer. | |
| 14 | |
| 15 2. Redistributions in binary form must reproduce the above copyright | |
| 16 notice, this list of conditions, and the disclaimer that follows | |
| 17 these conditions in the documentation and/or other materials | |
| 18 provided with the distribution. | |
| 19 | |
| 20 3. The name "JDOM" must not be used to endorse or promote products | |
| 21 derived from this software without prior written permission. For | |
| 22 written permission, please contact <request_AT_jdom_DOT_org>. | |
| 23 | |
| 24 4. Products derived from this software may not be called "JDOM", nor | |
| 25 may "JDOM" appear in their name, without prior written permission | |
| 26 from the JDOM Project Management <request_AT_jdom_DOT_org>. | |
| 27 | |
| 28 In addition, we request (but do not require) that you include in the | |
| 29 end-user documentation provided with the redistribution and/or in the | |
| 30 software itself an acknowledgement equivalent to the following: | |
| 31 "This product includes software developed by the | |
| 32 JDOM Project (http://www.jdom.org/)." | |
| 33 Alternatively, the acknowledgment may be graphical using the logos | |
| 34 available at http://www.jdom.org/images/logos. | |
| 35 | |
| 36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |
| 37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
| 38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT | |
| 40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
| 43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 47 SUCH DAMAGE. | |
| 48 | |
| 49 This software consists of voluntary contributions made by many | |
| 50 individuals on behalf of the JDOM Project and was originally | |
| 51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and | |
| 52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information | |
| 53 on the JDOM Project, please see <http://www.jdom.org/>. | |
| 54 | |
| 55 */ | |
| 56 | |
| 57 package org.jdom; | |
| 58 | |
| 59 import java.io.*; | |
| 60 import java.util.*; | |
| 61 | |
| 62 import org.jdom.filter.*; | |
| 63 | |
| 64 /** | |
| 65 * An XML element. Methods allow the user to get and manipulate its child | |
| 66 * elements and content, directly access the element's textual content, | |
| 67 * manipulate its attributes, and manage namespaces. | |
| 68 * | |
| 69 * @version $Revision: 1.159 $, $Date: 2007/11/14 05:02:08 $ | |
| 70 * @author Brett McLaughlin | |
| 71 * @author Jason Hunter | |
| 72 * @author Lucas Gonze | |
| 73 * @author Kevin Regan | |
| 74 * @author Dan Schaffer | |
| 75 * @author Yusuf Goolamabbas | |
| 76 * @author Kent C. Johnson | |
| 77 * @author Jools Enticknap | |
| 78 * @author Alex Rosen | |
| 79 * @author Bradley S. Huffman | |
| 80 * @author Victor Toni | |
| 81 */ | |
| 82 public class Element extends Content implements Parent { | |
| 83 | |
| 84 private static final String CVS_ID = | |
| 85 "@(#) $RCSfile: Element.java,v $ $Revision: 1.159 $ $Date: 2007/11/14 05:02:08 $ $Name: jdom_1_1_1 $"; | |
| 86 | |
| 87 private static final int INITIAL_ARRAY_SIZE = 5; | |
| 88 | |
| 89 /** The local name of the element */ | |
| 90 protected String name; | |
| 91 | |
| 92 /** The namespace of the element */ | |
| 93 protected transient Namespace namespace; | |
| 94 | |
| 95 /** Additional namespace declarations to store on this element; useful | |
| 96 * during output */ | |
| 97 protected transient List additionalNamespaces; | |
| 98 | |
| 99 // See http://lists.denveronline.net/lists/jdom-interest/2000-September/003030.html | |
| 100 // for a possible memory optimization here (using a RootElement subclass) | |
| 101 | |
| 102 /** | |
| 103 * The attributes of the element. Subclassers have to | |
| 104 * track attributes using their own mechanism. | |
| 105 */ | |
| 106 AttributeList attributes = new AttributeList(this); | |
| 107 | |
| 108 /** | |
| 109 * The content of the element. Subclassers have to | |
| 110 * track content using their own mechanism. | |
| 111 */ | |
| 112 ContentList content = new ContentList(this); | |
| 113 | |
| 114 /** | |
| 115 * This protected constructor is provided in order to support an Element | |
| 116 * subclass that wants full control over variable initialization. It | |
| 117 * intentionally leaves all instance variables null, allowing a lightweight | |
| 118 * subclass implementation. The subclass is responsible for ensuring all the | |
| 119 * get and set methods on Element behave as documented. | |
| 120 * <p> | |
| 121 * When implementing an Element subclass which doesn't require full control | |
| 122 * over variable initialization, be aware that simply calling super() (or | |
| 123 * letting the compiler add the implicit super() call) will not initialize | |
| 124 * the instance variables which will cause many of the methods to throw a | |
| 125 * NullPointerException. Therefore, the constructor for these subclasses | |
| 126 * should call one of the public constructors so variable initialization is | |
| 127 * handled automatically. | |
| 128 */ | |
| 129 protected Element() { } | |
| 130 | |
| 131 /** | |
| 132 * Creates a new element with the supplied (local) name and namespace. If | |
| 133 * the provided namespace is null, the element will have no namespace. | |
| 134 * | |
| 135 * @param name local name of the element | |
| 136 * @param namespace namespace for the element | |
| 137 * @throws IllegalNameException if the given name is illegal as an element | |
| 138 * name | |
| 139 */ | |
| 140 public Element(final String name, final Namespace namespace) { | |
| 141 setName(name); | |
| 142 setNamespace(namespace); | |
| 143 } | |
| 144 | |
| 145 /** | |
| 146 * Create a new element with the supplied (local) name and no namespace. | |
| 147 * | |
| 148 * @param name local name of the element | |
| 149 * @throws IllegalNameException if the given name is illegal as an element | |
| 150 * name. | |
| 151 */ | |
| 152 public Element(final String name) { | |
| 153 this(name, (Namespace) null); | |
| 154 } | |
| 155 | |
| 156 /** | |
| 157 * Creates a new element with the supplied (local) name and a namespace | |
| 158 * given by a URI. The element will be put into the unprefixed (default) | |
| 159 * namespace. | |
| 160 * | |
| 161 * @param name name of the element | |
| 162 * @param uri namespace URI for the element | |
| 163 * @throws IllegalNameException if the given name is illegal as an element | |
| 164 * name or the given URI is illegal as a | |
| 165 * namespace URI | |
| 166 */ | |
| 167 public Element(final String name, final String uri) { | |
| 168 this(name, Namespace.getNamespace("", uri)); | |
| 169 } | |
| 170 | |
| 171 /** | |
| 172 * Creates a new element with the supplied (local) name and a namespace | |
| 173 * given by the supplied prefix and URI combination. | |
| 174 * | |
| 175 * @param name local name of the element | |
| 176 * @param prefix namespace prefix | |
| 177 * @param uri namespace URI for the element | |
| 178 * @throws IllegalNameException if the given name is illegal as an element | |
| 179 * name, the given prefix is illegal as a | |
| 180 * namespace prefix, or the given URI is | |
| 181 * illegal as a namespace URI | |
| 182 */ | |
| 183 public Element(final String name, final String prefix, final String uri) { | |
| 184 this(name, Namespace.getNamespace(prefix, uri)); | |
| 185 } | |
| 186 | |
| 187 /** | |
| 188 * Returns the (local) name of the element (without any namespace prefix). | |
| 189 * | |
| 190 * @return local element name | |
| 191 */ | |
| 192 public String getName() { | |
| 193 return name; | |
| 194 } | |
| 195 | |
| 196 /** | |
| 197 * Sets the (local) name of the element. | |
| 198 * | |
| 199 * @param name the new (local) name of the element | |
| 200 * @return the target element | |
| 201 * @throws IllegalNameException if the given name is illegal as an Element | |
| 202 * name | |
| 203 */ | |
| 204 public Element setName(final String name) { | |
| 205 final String reason = Verifier.checkElementName(name); | |
| 206 if (reason != null) { | |
| 207 throw new IllegalNameException(name, "element", reason); | |
| 208 } | |
| 209 this.name = name; | |
| 210 return this; | |
| 211 } | |
| 212 | |
| 213 /** | |
| 214 * Returns the element's {@link Namespace}. | |
| 215 * | |
| 216 * @return the element's namespace | |
| 217 */ | |
| 218 public Namespace getNamespace() { | |
| 219 return namespace; | |
| 220 } | |
| 221 | |
| 222 /** | |
| 223 * Sets the element's {@link Namespace}. If the provided namespace is null, | |
| 224 * the element will have no namespace. | |
| 225 * | |
| 226 * @param namespace the new namespace | |
| 227 * @return the target element | |
| 228 */ | |
| 229 public Element setNamespace(Namespace namespace) { | |
| 230 if (namespace == null) { | |
| 231 namespace = Namespace.NO_NAMESPACE; | |
| 232 } | |
| 233 | |
| 234 this.namespace = namespace; | |
| 235 return this; | |
| 236 } | |
| 237 | |
| 238 /** | |
| 239 * Returns the namespace prefix of the element or an empty string if none | |
| 240 * exists. | |
| 241 * | |
| 242 * @return the namespace prefix | |
| 243 */ | |
| 244 public String getNamespacePrefix() { | |
| 245 return namespace.getPrefix(); | |
| 246 } | |
| 247 | |
| 248 /** | |
| 249 * Returns the namespace URI mapped to this element's prefix (or the | |
| 250 * in-scope default namespace URI if no prefix). If no mapping is found, an | |
| 251 * empty string is returned. | |
| 252 * | |
| 253 * @return the namespace URI for this element | |
| 254 */ | |
| 255 public String getNamespaceURI() { | |
| 256 return namespace.getURI(); | |
| 257 } | |
| 258 | |
| 259 /** | |
| 260 * Returns the {@link Namespace} corresponding to the given prefix in scope | |
| 261 * for this element. This involves searching up the tree, so the results | |
| 262 * depend on the current location of the element. Returns null if there is | |
| 263 * no namespace in scope with the given prefix at this point in the | |
| 264 * document. | |
| 265 * | |
| 266 * @param prefix namespace prefix to look up | |
| 267 * @return the Namespace for this prefix at this | |
| 268 * location, or null if none | |
| 269 */ | |
| 270 public Namespace getNamespace(final String prefix) { | |
| 271 if (prefix == null) { | |
| 272 return null; | |
| 273 } | |
| 274 | |
| 275 if ("xml".equals(prefix)) { | |
| 276 // Namespace "xml" is always bound. | |
| 277 return Namespace.XML_NAMESPACE; | |
| 278 } | |
| 279 | |
| 280 // Check if the prefix is the prefix for this element | |
| 281 if (prefix.equals(getNamespacePrefix())) { | |
| 282 return getNamespace(); | |
| 283 } | |
| 284 | |
| 285 // Scan the additional namespaces | |
| 286 if (additionalNamespaces != null) { | |
| 287 for (int i = 0; i < additionalNamespaces.size(); i++) { | |
| 288 final Namespace ns = (Namespace) additionalNamespaces.get(i); | |
| 289 if (prefix.equals(ns.getPrefix())) { | |
| 290 return ns; | |
| 291 } | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 // If we still don't have a match, ask the parent | |
| 296 if (parent instanceof Element) { | |
| 297 return ((Element)parent).getNamespace(prefix); | |
| 298 } | |
| 299 | |
| 300 return null; | |
| 301 } | |
| 302 | |
| 303 /** | |
| 304 * Returns the full name of the element, in the form | |
| 305 * [namespacePrefix]:[localName]. If the element does not have a namespace | |
| 306 * prefix, then the local name is returned. | |
| 307 * | |
| 308 * @return qualified name of the element (including | |
| 309 * namespace prefix) | |
| 310 */ | |
| 311 public String getQualifiedName() { | |
| 312 // Note: Any changes here should be reflected in | |
| 313 // XMLOutputter.printQualifiedName() | |
| 314 if ("".equals(namespace.getPrefix())) { | |
| 315 return getName(); | |
| 316 } | |
| 317 | |
| 318 return new StringBuffer(namespace.getPrefix()) | |
| 319 .append(':') | |
| 320 .append(name) | |
| 321 .toString(); | |
| 322 } | |
| 323 | |
| 324 /** | |
| 325 * Adds a namespace declarations to this element. This should <i>not</i> be | |
| 326 * used to add the declaration for this element itself; that should be | |
| 327 * assigned in the construction of the element. Instead, this is for adding | |
| 328 * namespace declarations on the element not relating directly to itself. | |
| 329 * It's used during output to for stylistic reasons move namespace | |
| 330 * declarations higher in the tree than they would have to be. | |
| 331 * | |
| 332 * @param additionalNamespace namespace to add | |
| 333 * @throws IllegalAddException if the namespace prefix collides with another | |
| 334 * namespace prefix on the element | |
| 335 */ | |
| 336 public void addNamespaceDeclaration(final Namespace additionalNamespace) { | |
| 337 | |
| 338 // Verify the new namespace prefix doesn't collide with another | |
| 339 // declared namespace, an attribute prefix, or this element's prefix | |
| 340 final String reason = Verifier.checkNamespaceCollision(additionalNamespace, this); | |
| 341 if (reason != null) { | |
| 342 throw new IllegalAddException(this, additionalNamespace, reason); | |
| 343 } | |
| 344 | |
| 345 if (additionalNamespaces == null) { | |
| 346 additionalNamespaces = new ArrayList(INITIAL_ARRAY_SIZE); | |
| 347 } | |
| 348 | |
| 349 additionalNamespaces.add(additionalNamespace); | |
| 350 } | |
| 351 | |
| 352 /** | |
| 353 * Removes an additional namespace declarations from this element. This | |
| 354 * should <i>not</i> be used to remove the declaration for this element | |
| 355 * itself; that should be handled in the construction of the element. | |
| 356 * Instead, this is for removing namespace declarations on the element not | |
| 357 * relating directly to itself. If the declaration is not present, this | |
| 358 * method does nothing. | |
| 359 * | |
| 360 * @param additionalNamespace namespace to remove | |
| 361 */ | |
| 362 public void removeNamespaceDeclaration(final Namespace additionalNamespace) { | |
| 363 if (additionalNamespaces == null) { | |
| 364 return; | |
| 365 } | |
| 366 additionalNamespaces.remove(additionalNamespace); | |
| 367 } | |
| 368 | |
| 369 /** | |
| 370 * Returns a list of the additional namespace declarations on this element. | |
| 371 * This includes only additional namespace, not the namespace of the element | |
| 372 * itself, which can be obtained through {@link #getNamespace()}. If there | |
| 373 * are no additional declarations, this returns an empty list. Note, the | |
| 374 * returned list is unmodifiable. | |
| 375 * | |
| 376 * @return a List of the additional namespace | |
| 377 * declarations | |
| 378 */ | |
| 379 public List getAdditionalNamespaces() { | |
| 380 // Not having the returned list be live allows us to avoid creating a | |
| 381 // new list object when XMLOutputter calls this method on an element | |
| 382 // with an empty list. | |
| 383 if (additionalNamespaces == null) { | |
| 384 return Collections.EMPTY_LIST; | |
| 385 } | |
| 386 return Collections.unmodifiableList(additionalNamespaces); | |
| 387 } | |
| 388 | |
| 389 /** | |
| 390 * Returns the XPath 1.0 string value of this element, which is the | |
| 391 * complete, ordered content of all text node descendants of this element | |
| 392 * (i.e. the text that's left after all references are resolved | |
| 393 * and all other markup is stripped out.) | |
| 394 * | |
| 395 * @return a concatentation of all text node descendants | |
| 396 */ | |
| 397 public String getValue() { | |
| 398 final StringBuffer buffer = new StringBuffer(); | |
| 399 | |
| 400 final Iterator iter = getContent().iterator(); | |
| 401 while (iter.hasNext()) { | |
| 402 final Content child = (Content) iter.next(); | |
| 403 if (child instanceof Element || child instanceof Text) { | |
| 404 buffer.append(child.getValue()); | |
| 405 } | |
| 406 } | |
| 407 return buffer.toString(); | |
| 408 } | |
| 409 | |
| 410 /** | |
| 411 * Returns whether this element is a root element. This can be used in | |
| 412 * tandem with {@link #getParent} to determine if an element has any | |
| 413 * "attachments" to a parent element or document. | |
| 414 * | |
| 415 * @return whether this is a root element | |
| 416 */ | |
| 417 public boolean isRootElement() { | |
| 418 return parent instanceof Document; | |
| 419 } | |
| 420 | |
| 421 public int getContentSize() { | |
| 422 return content.size(); | |
| 423 } | |
| 424 | |
| 425 public int indexOf(final Content child) { | |
| 426 return content.indexOf(child); | |
| 427 } | |
| 428 | |
| 429 // private int indexOf(int start, Filter filter) { | |
| 430 // int size = getContentSize(); | |
| 431 // for (int i = start; i < size; i++) { | |
| 432 // if (filter.matches(getContent(i))) { | |
| 433 // return i; | |
| 434 // } | |
| 435 // } | |
| 436 // return -1; | |
| 437 // } | |
| 438 | |
| 439 | |
| 440 /** | |
| 441 * Returns the textual content directly held under this element as a string. | |
| 442 * This includes all text within this single element, including whitespace | |
| 443 * and CDATA sections if they exist. It's essentially the concatenation of | |
| 444 * all {@link Text} and {@link CDATA} nodes returned by {@link #getContent}. | |
| 445 * The call does not recurse into child elements. If no textual value exists | |
| 446 * for the element, an empty string is returned. | |
| 447 * | |
| 448 * @return text content for this element, or empty | |
| 449 * string if none | |
| 450 */ | |
| 451 public String getText() { | |
| 452 if (content.size() == 0) { | |
| 453 return ""; | |
| 454 } | |
| 455 | |
| 456 // If we hold only a Text or CDATA, return it directly | |
| 457 if (content.size() == 1) { | |
| 458 final Object obj = content.get(0); | |
| 459 if (obj instanceof Text) { | |
| 460 return ((Text) obj).getText(); | |
| 461 } | |
| 462 else { | |
| 463 return ""; | |
| 464 } | |
| 465 } | |
| 466 | |
| 467 // Else build String up | |
| 468 final StringBuffer textContent = new StringBuffer(); | |
| 469 boolean hasText = false; | |
| 470 | |
| 471 for (int i = 0; i < content.size(); i++) { | |
| 472 final Object obj = content.get(i); | |
| 473 if (obj instanceof Text) { | |
| 474 textContent.append(((Text) obj).getText()); | |
| 475 hasText = true; | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 if (!hasText) { | |
| 480 return ""; | |
| 481 } | |
| 482 else { | |
| 483 return textContent.toString(); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 /** | |
| 488 * Returns the textual content of this element with all surrounding | |
| 489 * whitespace removed. If no textual value exists for the element, or if | |
| 490 * only whitespace exists, the empty string is returned. | |
| 491 * | |
| 492 * @return trimmed text content for this element, or | |
| 493 * empty string if none | |
| 494 */ | |
| 495 public String getTextTrim() { | |
| 496 return getText().trim(); | |
| 497 } | |
| 498 | |
| 499 /** | |
| 500 * Returns the textual content of this element with all surrounding | |
| 501 * whitespace removed and internal whitespace normalized to a single space. | |
| 502 * If no textual value exists for the element, or if only whitespace exists, | |
| 503 * the empty string is returned. | |
| 504 * | |
| 505 * @return normalized text content for this element, or | |
| 506 * empty string if none | |
| 507 */ | |
| 508 public String getTextNormalize() { | |
| 509 return Text.normalizeString(getText()); | |
| 510 } | |
| 511 | |
| 512 /** | |
| 513 * Returns the textual content of the named child element, or null if | |
| 514 * there's no such child. This method is a convenience because calling | |
| 515 * <code>getChild().getText()</code> can throw a NullPointerException. | |
| 516 * | |
| 517 * @param name the name of the child | |
| 518 * @return text content for the named child, or null if | |
| 519 * no such child | |
| 520 */ | |
| 521 public String getChildText(final String name) { | |
| 522 final Element child = getChild(name); | |
| 523 if (child == null) { | |
| 524 return null; | |
| 525 } | |
| 526 return child.getText(); | |
| 527 } | |
| 528 | |
| 529 /** | |
| 530 * Returns the trimmed textual content of the named child element, or null | |
| 531 * if there's no such child. See <code>{@link #getTextTrim()}</code> for | |
| 532 * details of text trimming. | |
| 533 * | |
| 534 * @param name the name of the child | |
| 535 * @return trimmed text content for the named child, or | |
| 536 * null if no such child | |
| 537 */ | |
| 538 public String getChildTextTrim(final String name) { | |
| 539 final Element child = getChild(name); | |
| 540 if (child == null) { | |
| 541 return null; | |
| 542 } | |
| 543 return child.getTextTrim(); | |
| 544 } | |
| 545 | |
| 546 /** | |
| 547 * Returns the normalized textual content of the named child element, or | |
| 548 * null if there's no such child. See <code>{@link | |
| 549 * #getTextNormalize()}</code> for details of text normalizing. | |
| 550 * | |
| 551 * @param name the name of the child | |
| 552 * @return normalized text content for the named child, | |
| 553 * or null if no such child | |
| 554 */ | |
| 555 public String getChildTextNormalize(final String name) { | |
| 556 final Element child = getChild(name); | |
| 557 if (child == null) { | |
| 558 return null; | |
| 559 } | |
| 560 return child.getTextNormalize(); | |
| 561 } | |
| 562 | |
| 563 /** | |
| 564 * Returns the textual content of the named child element, or null if | |
| 565 * there's no such child. | |
| 566 * | |
| 567 * @param name the name of the child | |
| 568 * @param ns the namespace of the child | |
| 569 * @return text content for the named child, or null if | |
| 570 * no such child | |
| 571 */ | |
| 572 public String getChildText(final String name, final Namespace ns) { | |
| 573 final Element child = getChild(name, ns); | |
| 574 if (child == null) { | |
| 575 return null; | |
| 576 } | |
| 577 return child.getText(); | |
| 578 } | |
| 579 | |
| 580 /** | |
| 581 * Returns the trimmed textual content of the named child element, or null | |
| 582 * if there's no such child. | |
| 583 * | |
| 584 * @param name the name of the child | |
| 585 * @param ns the namespace of the child | |
| 586 * @return trimmed text content for the named child, or | |
| 587 * null if no such child | |
| 588 */ | |
| 589 public String getChildTextTrim(final String name, final Namespace ns) { | |
| 590 final Element child = getChild(name, ns); | |
| 591 if (child == null) { | |
| 592 return null; | |
| 593 } | |
| 594 return child.getTextTrim(); | |
| 595 } | |
| 596 | |
| 597 /** | |
| 598 * Returns the normalized textual content of the named child element, or | |
| 599 * null if there's no such child. | |
| 600 * | |
| 601 * @param name the name of the child | |
| 602 * @param ns the namespace of the child | |
| 603 * @return normalized text content for the named child, | |
| 604 * or null if no such child | |
| 605 */ | |
| 606 public String getChildTextNormalize(final String name, final Namespace ns) { | |
| 607 final Element child = getChild(name, ns); | |
| 608 if (child == null) { | |
| 609 return null; | |
| 610 } | |
| 611 return child.getTextNormalize(); | |
| 612 } | |
| 613 | |
| 614 /** | |
| 615 * Sets the content of the element to be the text given. All existing text | |
| 616 * content and non-text context is removed. If this element should have both | |
| 617 * textual content and nested elements, use <code>{@link #setContent}</code> | |
| 618 * instead. Setting a null text value is equivalent to setting an empty | |
| 619 * string value. | |
| 620 * | |
| 621 * @param text new text content for the element | |
| 622 * @return the target element | |
| 623 * @throws IllegalDataException if the assigned text contains an illegal | |
| 624 * character such as a vertical tab (as | |
| 625 * determined by {@link | |
| 626 * org.jdom.Verifier#checkCharacterData}) | |
| 627 */ | |
| 628 public Element setText(final String text) { | |
| 629 content.clear(); | |
| 630 | |
| 631 if (text != null) { | |
| 632 addContent(new Text(text)); | |
| 633 } | |
| 634 | |
| 635 return this; | |
| 636 } | |
| 637 | |
| 638 /** | |
| 639 * This returns the full content of the element as a List which | |
| 640 * may contain objects of type <code>Text</code>, <code>Element</code>, | |
| 641 * <code>Comment</code>, <code>ProcessingInstruction</code>, | |
| 642 * <code>CDATA</code>, and <code>EntityRef</code>. | |
| 643 * The List returned is "live" in document order and modifications | |
| 644 * to it affect the element's actual contents. Whitespace content is | |
| 645 * returned in its entirety. | |
| 646 * | |
| 647 * <p> | |
| 648 * Sequential traversal through the List is best done with an Iterator | |
| 649 * since the underlying implement of List.size() may require walking the | |
| 650 * entire list. | |
| 651 * </p> | |
| 652 * | |
| 653 * @return a <code>List</code> containing the mixed content of the | |
| 654 * element: may contain <code>Text</code>, | |
| 655 * <code>{@link Element}</code>, <code>{@link Comment}</code>, | |
| 656 * <code>{@link ProcessingInstruction}</code>, | |
| 657 * <code>{@link CDATA}</code>, and | |
| 658 * <code>{@link EntityRef}</code> objects. | |
| 659 */ | |
| 660 public List getContent() { | |
| 661 return content; | |
| 662 } | |
| 663 | |
| 664 /** | |
| 665 * Return a filter view of this <code>Element</code>'s content. | |
| 666 * | |
| 667 * <p> | |
| 668 * Sequential traversal through the List is best done with a Iterator | |
| 669 * since the underlying implement of List.size() may require walking the | |
| 670 * entire list. | |
| 671 * </p> | |
| 672 * | |
| 673 * @param filter <code>Filter</code> to apply | |
| 674 * @return <code>List</code> - filtered Element content | |
| 675 */ | |
| 676 public List getContent(final Filter filter) { | |
| 677 return content.getView(filter); | |
| 678 } | |
| 679 | |
| 680 /** | |
| 681 * Removes all child content from this parent. | |
| 682 * | |
| 683 * @return list of the old children detached from this parent | |
| 684 */ | |
| 685 public List removeContent() { | |
| 686 final List old = new ArrayList(content); | |
| 687 content.clear(); | |
| 688 return old; | |
| 689 } | |
| 690 | |
| 691 /** | |
| 692 * Remove all child content from this parent matching the supplied filter. | |
| 693 * | |
| 694 * @param filter filter to select which content to remove | |
| 695 * @return list of the old children detached from this parent | |
| 696 */ | |
| 697 public List removeContent(final Filter filter) { | |
| 698 final List old = new ArrayList(); | |
| 699 final Iterator iter = content.getView(filter).iterator(); | |
| 700 while (iter.hasNext()) { | |
| 701 final Content child = (Content) iter.next(); | |
| 702 old.add(child); | |
| 703 iter.remove(); | |
| 704 } | |
| 705 return old; | |
| 706 } | |
| 707 | |
| 708 /** | |
| 709 * This sets the content of the element. The supplied List should | |
| 710 * contain only objects of type <code>Element</code>, <code>Text</code>, | |
| 711 * <code>CDATA</code>, <code>Comment</code>, | |
| 712 * <code>ProcessingInstruction</code>, and <code>EntityRef</code>. | |
| 713 * | |
| 714 * <p> | |
| 715 * When all objects in the supplied List are legal and before the new | |
| 716 * content is added, all objects in the old content will have their | |
| 717 * parentage set to null (no parent) and the old content list will be | |
| 718 * cleared. This has the effect that any active list (previously obtained | |
| 719 * with a call to {@link #getContent} or {@link #getChildren}) will also | |
| 720 * change to reflect the new content. In addition, all objects in the | |
| 721 * supplied List will have their parentage set to this element, but the | |
| 722 * List itself will not be "live" and further removals and additions will | |
| 723 * have no effect on this elements content. If the user wants to continue | |
| 724 * working with a "live" list, then a call to setContent should be | |
| 725 * followed by a call to {@link #getContent} or {@link #getChildren} to | |
| 726 * obtain a "live" version of the content. | |
| 727 * </p> | |
| 728 * | |
| 729 * <p> | |
| 730 * Passing a null or empty List clears the existing content. | |
| 731 * </p> | |
| 732 * | |
| 733 * <p> | |
| 734 * In event of an exception the original content will be unchanged and | |
| 735 * the objects in the supplied content will be unaltered. | |
| 736 * </p> | |
| 737 * | |
| 738 * @param newContent <code>Collection</code> of content to set | |
| 739 * @return this element modified | |
| 740 * @throws IllegalAddException if the List contains objects of | |
| 741 * illegal types or with existing parentage. | |
| 742 */ | |
| 743 public Element setContent(final Collection newContent) { | |
| 744 content.clearAndSet(newContent); | |
| 745 return this; | |
| 746 } | |
| 747 | |
| 748 /** | |
| 749 * Replace the current child the given index with the supplied child. | |
| 750 * <p> | |
| 751 * In event of an exception the original content will be unchanged and | |
| 752 * the supplied child will be unaltered. | |
| 753 * </p> | |
| 754 * | |
| 755 * @param index - index of child to replace. | |
| 756 * @param child - child to add. | |
| 757 * @return element on which this method was invoked | |
| 758 * @throws IllegalAddException if the supplied child is already attached | |
| 759 * or not legal content for this parent. | |
| 760 * @throws IndexOutOfBoundsException if index is negative or greater | |
| 761 * than the current number of children. | |
| 762 */ | |
| 763 public Element setContent(final int index, final Content child) { | |
| 764 content.set(index, child); | |
| 765 return this; | |
| 766 } | |
| 767 | |
| 768 /** | |
| 769 * Replace the child at the given index whith the supplied | |
| 770 * collection. | |
| 771 * <p> | |
| 772 * In event of an exception the original content will be unchanged and | |
| 773 * the content in the supplied collection will be unaltered. | |
| 774 * </p> | |
| 775 * | |
| 776 * @param index - index of child to replace. | |
| 777 * @param newContent - <code>Collection</code> of content to replace child. | |
| 778 * @return object on which this method was invoked | |
| 779 * @throws IllegalAddException if the collection contains objects of | |
| 780 * illegal types. | |
| 781 * @throws IndexOutOfBoundsException if index is negative or greater | |
| 782 * than the current number of children. | |
| 783 */ | |
| 784 public Parent setContent(final int index, final Collection newContent) { | |
| 785 content.remove(index); | |
| 786 content.addAll(index, newContent); | |
| 787 return this; | |
| 788 } | |
| 789 | |
| 790 /** | |
| 791 * This adds text content to this element. It does not replace the | |
| 792 * existing content as does <code>setText()</code>. | |
| 793 * | |
| 794 * @param str <code>String</code> to add | |
| 795 * @return this element modified | |
| 796 * @throws IllegalDataException if <code>str</code> contains an | |
| 797 * illegal character such as a vertical tab (as determined | |
| 798 * by {@link org.jdom.Verifier#checkCharacterData}) | |
| 799 */ | |
| 800 public Element addContent(final String str) { | |
| 801 return addContent(new Text(str)); | |
| 802 } | |
| 803 | |
| 804 /** | |
| 805 * Appends the child to the end of the element's content list. | |
| 806 * | |
| 807 * @param child child to append to end of content list | |
| 808 * @return the element on which the method was called | |
| 809 * @throws IllegalAddException if the given child already has a parent. */ | |
| 810 public Element addContent(final Content child) { | |
| 811 content.add(child); | |
| 812 return this; | |
| 813 } | |
| 814 | |
| 815 /** | |
| 816 * Appends all children in the given collection to the end of | |
| 817 * the content list. In event of an exception during add the | |
| 818 * original content will be unchanged and the objects in the supplied | |
| 819 * collection will be unaltered. | |
| 820 * | |
| 821 * @param newContent <code>Collection</code> of content to append | |
| 822 * @return the element on which the method was called | |
| 823 * @throws IllegalAddException if any item in the collection | |
| 824 * already has a parent or is of an inappropriate type. | |
| 825 */ | |
| 826 public Element addContent(final Collection newContent) { | |
| 827 content.addAll(newContent); | |
| 828 return this; | |
| 829 } | |
| 830 | |
| 831 /** | |
| 832 * Inserts the child into the content list at the given index. | |
| 833 * | |
| 834 * @param index location for adding the collection | |
| 835 * @param child child to insert | |
| 836 * @return the parent on which the method was called | |
| 837 * @throws IndexOutOfBoundsException if index is negative or beyond | |
| 838 * the current number of children | |
| 839 * @throws IllegalAddException if the given child already has a parent. | |
| 840 */ | |
| 841 public Element addContent(final int index, final Content child) { | |
| 842 content.add(index, child); | |
| 843 return this; | |
| 844 } | |
| 845 | |
| 846 /** | |
| 847 * Inserts the content in a collection into the content list | |
| 848 * at the given index. In event of an exception the original content | |
| 849 * will be unchanged and the objects in the supplied collection will be | |
| 850 * unaltered. | |
| 851 * | |
| 852 * @param index location for adding the collection | |
| 853 * @param newContent <code>Collection</code> of content to insert | |
| 854 * @return the parent on which the method was called | |
| 855 * @throws IndexOutOfBoundsException if index is negative or beyond | |
| 856 * the current number of children | |
| 857 * @throws IllegalAddException if any item in the collection | |
| 858 * already has a parent or is of an inappropriate type. | |
| 859 */ | |
| 860 public Element addContent(final int index, final Collection newContent) { | |
| 861 content.addAll(index, newContent); | |
| 862 return this; | |
| 863 } | |
| 864 | |
| 865 public List cloneContent() { | |
| 866 final int size = getContentSize(); | |
| 867 final List list = new ArrayList(size); | |
| 868 for (int i = 0; i < size; i++) { | |
| 869 final Content child = getContent(i); | |
| 870 list.add(child.clone()); | |
| 871 } | |
| 872 return list; | |
| 873 } | |
| 874 | |
| 875 public Content getContent(final int index) { | |
| 876 return (Content) content.get(index); | |
| 877 } | |
| 878 | |
| 879 // public Content getChild(Filter filter) { | |
| 880 // int i = indexOf(0, filter); | |
| 881 // return (i < 0) ? null : getContent(i); | |
| 882 // } | |
| 883 | |
| 884 public boolean removeContent(final Content child) { | |
| 885 return content.remove(child); | |
| 886 } | |
| 887 | |
| 888 public Content removeContent(final int index) { | |
| 889 return (Content) content.remove(index); | |
| 890 } | |
| 891 | |
| 892 /** | |
| 893 * Set this element's content to be the supplied child. | |
| 894 * <p> | |
| 895 * If the supplied child is legal content for this parent and before | |
| 896 * it is added, all content in the current content list will | |
| 897 * be cleared and all current children will have their parentage set to | |
| 898 * null. | |
| 899 * <p> | |
| 900 * This has the effect that any active list (previously obtained with | |
| 901 * a call to one of the {@link #getContent} methods will also change | |
| 902 * to reflect the new content. In addition, all content in the supplied | |
| 903 * collection will have their parentage set to this parent. If the user | |
| 904 * wants to continue working with a <b>"live"</b> list of this parent's | |
| 905 * child, then a call to setContent should be followed by a call to one | |
| 906 * of the {@link #getContent} methods to obtain a <b>"live"</b> | |
| 907 * version of the children. | |
| 908 * <p> | |
| 909 * Passing a null child clears the existing content. | |
| 910 * <p> | |
| 911 * In event of an exception the original content will be unchanged and | |
| 912 * the supplied child will be unaltered. | |
| 913 * | |
| 914 * @param child new content to replace existing content | |
| 915 * @return the parent on which the method was called | |
| 916 * @throws IllegalAddException if the supplied child is already attached | |
| 917 * or not legal content for an Element | |
| 918 */ | |
| 919 public Element setContent(final Content child) { | |
| 920 content.clear(); | |
| 921 content.add(child); | |
| 922 return this; | |
| 923 } | |
| 924 | |
| 925 | |
| 926 /** | |
| 927 * Determines if this element is the ancestor of another element. | |
| 928 * | |
| 929 * @param element <code>Element</code> to check against | |
| 930 * @return <code>true</code> if this element is the ancestor of the | |
| 931 * supplied element | |
| 932 */ | |
| 933 public boolean isAncestor(final Element element) { | |
| 934 Parent p = element.getParent(); | |
| 935 while (p instanceof Element) { | |
| 936 if (p == this) { | |
| 937 return true; | |
| 938 } | |
| 939 p = p.getParent(); | |
| 940 } | |
| 941 return false; | |
| 942 } | |
| 943 | |
| 944 /** | |
| 945 * <p> | |
| 946 * This returns the complete set of attributes for this element, as a | |
| 947 * <code>List</code> of <code>Attribute</code> objects in no particular | |
| 948 * order, or an empty list if there are none. | |
| 949 * The returned list is "live" and changes to it affect the | |
| 950 * element's actual attributes. | |
| 951 * </p> | |
| 952 * | |
| 953 * @return attributes for the element | |
| 954 */ | |
| 955 public List getAttributes() { | |
| 956 return attributes; | |
| 957 } | |
| 958 | |
| 959 /** | |
| 960 * <p> | |
| 961 * This returns the attribute for this element with the given name | |
| 962 * and within no namespace, or null if no such attribute exists. | |
| 963 * </p> | |
| 964 * | |
| 965 * @param name name of the attribute to return | |
| 966 * @return attribute for the element | |
| 967 */ | |
| 968 public Attribute getAttribute(final String name) { | |
| 969 return getAttribute(name, Namespace.NO_NAMESPACE); | |
| 970 } | |
| 971 | |
| 972 /** | |
| 973 * <p> | |
| 974 * This returns the attribute for this element with the given name | |
| 975 * and within the given Namespace, or null if no such attribute exists. | |
| 976 * </p> | |
| 977 * | |
| 978 * @param name name of the attribute to return | |
| 979 * @param ns <code>Namespace</code> to search within | |
| 980 * @return attribute for the element | |
| 981 */ | |
| 982 public Attribute getAttribute(final String name, final Namespace ns) { | |
| 983 return (Attribute) attributes.get(name, ns); | |
| 984 } | |
| 985 | |
| 986 /** | |
| 987 * <p> | |
| 988 * This returns the attribute value for the attribute with the given name | |
| 989 * and within no namespace, null if there is no such attribute, and the | |
| 990 * empty string if the attribute value is empty. | |
| 991 * </p> | |
| 992 * | |
| 993 * @param name name of the attribute whose value to be returned | |
| 994 * @return the named attribute's value, or null if no such attribute | |
| 995 */ | |
| 996 public String getAttributeValue(final String name) { | |
| 997 return getAttributeValue(name, Namespace.NO_NAMESPACE); | |
| 998 } | |
| 999 | |
| 1000 /** | |
| 1001 * <p> | |
| 1002 * This returns the attribute value for the attribute with the given name | |
| 1003 * and within no namespace, or the passed-in default if there is no | |
| 1004 * such attribute. | |
| 1005 * </p> | |
| 1006 * | |
| 1007 * @param name name of the attribute whose value to be returned | |
| 1008 * @param def a default value to return if the attribute does not exist | |
| 1009 * @return the named attribute's value, or the default if no such attribute | |
| 1010 */ | |
| 1011 public String getAttributeValue(final String name, final String def) { | |
| 1012 return getAttributeValue(name, Namespace.NO_NAMESPACE, def); | |
| 1013 } | |
| 1014 | |
| 1015 /** | |
| 1016 * <p> | |
| 1017 * This returns the attribute value for the attribute with the given name | |
| 1018 * and within the given Namespace, null if there is no such attribute, and | |
| 1019 * the empty string if the attribute value is empty. | |
| 1020 * </p> | |
| 1021 * | |
| 1022 * @param name name of the attribute whose valud is to be returned | |
| 1023 * @param ns <code>Namespace</code> to search within | |
| 1024 * @return the named attribute's value, or null if no such attribute | |
| 1025 */ | |
| 1026 public String getAttributeValue(final String name, final Namespace ns) { | |
| 1027 return getAttributeValue(name, ns, null); | |
| 1028 } | |
| 1029 | |
| 1030 /** | |
| 1031 * <p> | |
| 1032 * This returns the attribute value for the attribute with the given name | |
| 1033 * and within the given Namespace, or the passed-in default if there is no | |
| 1034 * such attribute. | |
| 1035 * </p> | |
| 1036 * | |
| 1037 * @param name name of the attribute whose valud is to be returned | |
| 1038 * @param ns <code>Namespace</code> to search within | |
| 1039 * @param def a default value to return if the attribute does not exist | |
| 1040 * @return the named attribute's value, or the default if no such attribute | |
| 1041 */ | |
| 1042 public String getAttributeValue(final String name, final Namespace ns, final String def) { | |
| 1043 final Attribute attribute = (Attribute) attributes.get(name, ns); | |
| 1044 if (attribute == null) { | |
| 1045 return def; | |
| 1046 } | |
| 1047 | |
| 1048 return attribute.getValue(); | |
| 1049 } | |
| 1050 | |
| 1051 /** | |
| 1052 * <p> | |
| 1053 * This sets the attributes of the element. The supplied Collection should | |
| 1054 * contain only objects of type <code>Attribute</code>. | |
| 1055 * </p> | |
| 1056 * | |
| 1057 * <p> | |
| 1058 * When all objects in the supplied List are legal and before the new | |
| 1059 * attributes are added, all old attributes will have their | |
| 1060 * parentage set to null (no parent) and the old attribute list will be | |
| 1061 * cleared. This has the effect that any active attribute list (previously | |
| 1062 * obtained with a call to {@link #getAttributes}) will also change to | |
| 1063 * reflect the new attributes. In addition, all attributes in the supplied | |
| 1064 * List will have their parentage set to this element, but the List itself | |
| 1065 * will not be "live" and further removals and additions will have no | |
| 1066 * effect on this elements attributes. If the user wants to continue | |
| 1067 * working with a "live" attribute list, then a call to setAttributes | |
| 1068 * should be followed by a call to {@link #getAttributes} to obtain a | |
| 1069 * "live" version of the attributes. | |
| 1070 * </p> | |
| 1071 * | |
| 1072 * <p> | |
| 1073 * Passing a null or empty List clears the existing attributes. | |
| 1074 * </p> | |
| 1075 * | |
| 1076 * <p> | |
| 1077 * In cases where the List contains duplicate attributes, only the last | |
| 1078 * one will be retained. This has the same effect as calling | |
| 1079 * {@link #setAttribute(Attribute)} sequentially. | |
| 1080 * </p> | |
| 1081 * | |
| 1082 * <p> | |
| 1083 * In event of an exception the original attributes will be unchanged and | |
| 1084 * the attributes in the supplied attributes will be unaltered. | |
| 1085 * </p> | |
| 1086 * | |
| 1087 * @param newAttributes <code>Collection</code> of attributes to set | |
| 1088 * @return this element modified | |
| 1089 * @throws IllegalAddException if the List contains objects | |
| 1090 * that are not instances of <code>Attribute</code>, | |
| 1091 * or if any of the <code>Attribute</code> objects have | |
| 1092 * conflicting namespace prefixes. | |
| 1093 */ | |
| 1094 public Element setAttributes(final Collection newAttributes) { | |
| 1095 attributes.clearAndSet(newAttributes); | |
| 1096 return this; | |
| 1097 } | |
| 1098 | |
| 1099 /** | |
| 1100 * <p> | |
| 1101 * This sets the attributes of the element. It's an alternate form of | |
| 1102 * the method, accepting a <code>List</code> instead of a | |
| 1103 * <code>Collection</code>, for backward compatibility. | |
| 1104 * </p> | |
| 1105 */ | |
| 1106 public Element setAttributes(final List newAttributes) { | |
| 1107 return setAttributes((Collection)newAttributes); | |
| 1108 } | |
| 1109 | |
| 1110 /** | |
| 1111 * <p> | |
| 1112 * This sets an attribute value for this element. Any existing attribute | |
| 1113 * with the same name and namespace URI is removed. | |
| 1114 * </p> | |
| 1115 * | |
| 1116 * @param name name of the attribute to set | |
| 1117 * @param value value of the attribute to set | |
| 1118 * @return this element modified | |
| 1119 * @throws IllegalNameException if the given name is illegal as an | |
| 1120 * attribute name. | |
| 1121 * @throws IllegalDataException if the given attribute value is | |
| 1122 * illegal character data (as determined by | |
| 1123 * {@link org.jdom.Verifier#checkCharacterData}). | |
| 1124 */ | |
| 1125 public Element setAttribute(final String name, final String value) { | |
| 1126 final Attribute attribute = getAttribute(name); | |
| 1127 if (attribute == null) { | |
| 1128 final Attribute newAttribute = new Attribute(name, value); | |
| 1129 setAttribute(newAttribute); | |
| 1130 } else { | |
| 1131 attribute.setValue(value); | |
| 1132 } | |
| 1133 | |
| 1134 return this; | |
| 1135 } | |
| 1136 | |
| 1137 /** | |
| 1138 * <p> | |
| 1139 * This sets an attribute value for this element. Any existing attribute | |
| 1140 * with the same name and namespace URI is removed. | |
| 1141 * </p> | |
| 1142 * | |
| 1143 * @param name name of the attribute to set | |
| 1144 * @param value value of the attribute to set | |
| 1145 * @param ns namespace of the attribute to set | |
| 1146 * @return this element modified | |
| 1147 * @throws IllegalNameException if the given name is illegal as an | |
| 1148 * attribute name, or if the namespace is an unprefixed default | |
| 1149 * namespace | |
| 1150 * @throws IllegalDataException if the given attribute value is | |
| 1151 * illegal character data (as determined by | |
| 1152 * {@link org.jdom.Verifier#checkCharacterData}). | |
| 1153 * @throws IllegalAddException if the attribute namespace prefix | |
| 1154 * collides with another namespace prefix on the element. | |
| 1155 */ | |
| 1156 public Element setAttribute(final String name, final String value, final Namespace ns) { | |
| 1157 final Attribute attribute = getAttribute(name, ns); | |
| 1158 if (attribute == null) { | |
| 1159 final Attribute newAttribute = new Attribute(name, value, ns); | |
| 1160 setAttribute(newAttribute); | |
| 1161 } else { | |
| 1162 attribute.setValue(value); | |
| 1163 } | |
| 1164 | |
| 1165 return this; | |
| 1166 } | |
| 1167 | |
| 1168 /** | |
| 1169 * <p> | |
| 1170 * This sets an attribute value for this element. Any existing attribute | |
| 1171 * with the same name and namespace URI is removed. | |
| 1172 * </p> | |
| 1173 * | |
| 1174 * @param attribute <code>Attribute</code> to set | |
| 1175 * @return this element modified | |
| 1176 * @throws IllegalAddException if the attribute being added already has a | |
| 1177 * parent or if the attribute namespace prefix collides with another | |
| 1178 * namespace prefix on the element. | |
| 1179 */ | |
| 1180 public Element setAttribute(final Attribute attribute) { | |
| 1181 attributes.add(attribute); | |
| 1182 return this; | |
| 1183 } | |
| 1184 | |
| 1185 /** | |
| 1186 * <p> | |
| 1187 * This removes the attribute with the given name and within no | |
| 1188 * namespace. If no such attribute exists, this method does nothing. | |
| 1189 * </p> | |
| 1190 * | |
| 1191 * @param name name of attribute to remove | |
| 1192 * @return whether the attribute was removed | |
| 1193 */ | |
| 1194 public boolean removeAttribute(final String name) { | |
| 1195 return removeAttribute(name, Namespace.NO_NAMESPACE); | |
| 1196 } | |
| 1197 | |
| 1198 /** | |
| 1199 * <p> | |
| 1200 * This removes the attribute with the given name and within the | |
| 1201 * given Namespace. If no such attribute exists, this method does | |
| 1202 * nothing. | |
| 1203 * </p> | |
| 1204 * | |
| 1205 * @param name name of attribute to remove | |
| 1206 * @param ns namespace URI of attribute to remove | |
| 1207 * @return whether the attribute was removed | |
| 1208 */ | |
| 1209 public boolean removeAttribute(final String name, final Namespace ns) { | |
| 1210 return attributes.remove(name, ns); | |
| 1211 } | |
| 1212 | |
| 1213 /** | |
| 1214 * <p> | |
| 1215 * This removes the supplied Attribute should it exist. | |
| 1216 * </p> | |
| 1217 * | |
| 1218 * @param attribute Reference to the attribute to be removed. | |
| 1219 * @return whether the attribute was removed | |
| 1220 */ | |
| 1221 public boolean removeAttribute(final Attribute attribute) { | |
| 1222 return attributes.remove(attribute); | |
| 1223 } | |
| 1224 | |
| 1225 /** | |
| 1226 * <p> | |
| 1227 * This returns a <code>String</code> representation of the | |
| 1228 * <code>Element</code>, suitable for debugging. If the XML | |
| 1229 * representation of the <code>Element</code> is desired, | |
| 1230 * {@link org.jdom.output.XMLOutputter#outputString(Element)} | |
| 1231 * should be used. | |
| 1232 * </p> | |
| 1233 * | |
| 1234 * @return <code>String</code> - information about the | |
| 1235 * <code>Element</code> | |
| 1236 */ | |
| 1237 public String toString() { | |
| 1238 final StringBuffer stringForm = new StringBuffer(64) | |
| 1239 .append("[Element: <") | |
| 1240 .append(getQualifiedName()); | |
| 1241 | |
| 1242 final String nsuri = getNamespaceURI(); | |
| 1243 if (!"".equals(nsuri)) { | |
| 1244 stringForm | |
| 1245 .append(" [Namespace: ") | |
| 1246 .append(nsuri) | |
| 1247 .append("]"); | |
| 1248 } | |
| 1249 stringForm.append("/>]"); | |
| 1250 | |
| 1251 return stringForm.toString(); | |
| 1252 } | |
| 1253 | |
| 1254 /** | |
| 1255 * <p> | |
| 1256 * This returns a deep clone of this element. | |
| 1257 * The new element is detached from its parent, and getParent() | |
| 1258 * on the clone will return null. | |
| 1259 * </p> | |
| 1260 * | |
| 1261 * @return the clone of this element | |
| 1262 */ | |
| 1263 public Object clone() { | |
| 1264 | |
| 1265 // Ken Rune Helland <kenh@csc.no> is our local clone() guru | |
| 1266 | |
| 1267 final Element element = (Element) super.clone(); | |
| 1268 | |
| 1269 // name and namespace are references to immutable objects | |
| 1270 // so super.clone() handles them ok | |
| 1271 | |
| 1272 // Reference to parent is copied by super.clone() | |
| 1273 // (Object.clone()) so we have to remove it | |
| 1274 // Actually, super is a Content, which has already detached in the | |
| 1275 // clone(). | |
| 1276 // element.parent = null; | |
| 1277 | |
| 1278 // Reference to content list and attribute lists are copyed by | |
| 1279 // super.clone() so we set it new lists if the original had lists | |
| 1280 element.content = new ContentList(element); | |
| 1281 element.attributes = new AttributeList(element); | |
| 1282 | |
| 1283 // Cloning attributes | |
| 1284 if (attributes != null) { | |
| 1285 for(int i = 0; i < attributes.size(); i++) { | |
| 1286 final Attribute attribute = (Attribute) attributes.get(i); | |
| 1287 element.attributes.add(attribute.clone()); | |
| 1288 } | |
| 1289 } | |
| 1290 | |
| 1291 // Cloning additional namespaces | |
| 1292 if (additionalNamespaces != null) { | |
| 1293 element.additionalNamespaces = new ArrayList(additionalNamespaces); | |
| 1294 } | |
| 1295 | |
| 1296 // Cloning content | |
| 1297 if (content != null) { | |
| 1298 for(int i = 0; i < content.size(); i++) { | |
| 1299 final Content c = (Content) content.get(i); | |
| 1300 element.content.add(c.clone()); | |
| 1301 } | |
| 1302 } | |
| 1303 | |
| 1304 return element; | |
| 1305 } | |
| 1306 | |
| 1307 | |
| 1308 // Support a custom Namespace serialization so no two namespace | |
| 1309 // object instances may exist for the same prefix/uri pair | |
| 1310 private void writeObject(final ObjectOutputStream out) throws IOException { | |
| 1311 | |
| 1312 out.defaultWriteObject(); | |
| 1313 | |
| 1314 // We use writeObject() and not writeUTF() to minimize space | |
| 1315 // This allows for writing pointers to already written strings | |
| 1316 out.writeObject(namespace.getPrefix()); | |
| 1317 out.writeObject(namespace.getURI()); | |
| 1318 | |
| 1319 if (additionalNamespaces == null) { | |
| 1320 out.write(0); | |
| 1321 } | |
| 1322 else { | |
| 1323 final int size = additionalNamespaces.size(); | |
| 1324 out.write(size); | |
| 1325 for (int i = 0; i < size; i++) { | |
| 1326 final Namespace additional = (Namespace) additionalNamespaces.get(i); | |
| 1327 out.writeObject(additional.getPrefix()); | |
| 1328 out.writeObject(additional.getURI()); | |
| 1329 } | |
| 1330 } | |
| 1331 } | |
| 1332 | |
| 1333 private void readObject(final ObjectInputStream in) | |
| 1334 throws IOException, ClassNotFoundException { | |
| 1335 | |
| 1336 in.defaultReadObject(); | |
| 1337 | |
| 1338 namespace = Namespace.getNamespace( | |
| 1339 (String)in.readObject(), (String)in.readObject()); | |
| 1340 | |
| 1341 final int size = in.read(); | |
| 1342 | |
| 1343 if (size != 0) { | |
| 1344 additionalNamespaces = new ArrayList(size); | |
| 1345 for (int i = 0; i < size; i++) { | |
| 1346 final Namespace additional = Namespace.getNamespace( | |
| 1347 (String)in.readObject(), (String)in.readObject()); | |
| 1348 additionalNamespaces.add(additional); | |
| 1349 } | |
| 1350 } | |
| 1351 } | |
| 1352 | |
| 1353 /** | |
| 1354 * Returns an iterator that walks over all descendants in document order. | |
| 1355 * | |
| 1356 * @return an iterator to walk descendants | |
| 1357 */ | |
| 1358 public Iterator getDescendants() { | |
| 1359 return new DescendantIterator(this); | |
| 1360 } | |
| 1361 | |
| 1362 /** | |
| 1363 * Returns an iterator that walks over all descendants in document order | |
| 1364 * applying the Filter to return only elements that match the filter rule. | |
| 1365 * With filters you can match only Elements, only Comments, Elements or | |
| 1366 * Comments, only Elements with a given name and/or prefix, and so on. | |
| 1367 * | |
| 1368 * @param filter filter to select which descendants to see | |
| 1369 * @return an iterator to walk descendants within a filter | |
| 1370 */ | |
| 1371 public Iterator getDescendants(final Filter filter) { | |
| 1372 final Iterator iterator = new DescendantIterator(this); | |
| 1373 return new FilterIterator(iterator, filter); | |
| 1374 } | |
| 1375 | |
| 1376 | |
| 1377 | |
| 1378 /** | |
| 1379 * This returns a <code>List</code> of all the child elements | |
| 1380 * nested directly (one level deep) within this element, as | |
| 1381 * <code>Element</code> objects. If this target element has no nested | |
| 1382 * elements, an empty List is returned. The returned list is "live" | |
| 1383 * in document order and changes to it affect the element's actual | |
| 1384 * contents. | |
| 1385 * | |
| 1386 * <p> | |
| 1387 * Sequential traversal through the List is best done with a Iterator | |
| 1388 * since the underlying implement of List.size() may not be the most | |
| 1389 * efficient. | |
| 1390 * </p> | |
| 1391 * | |
| 1392 * <p> | |
| 1393 * No recursion is performed, so elements nested two levels deep | |
| 1394 * would have to be obtained with: | |
| 1395 * <pre> | |
| 1396 * <code> | |
| 1397 * Iterator itr = (currentElement.getChildren()).iterator(); | |
| 1398 * while(itr.hasNext()) { | |
| 1399 * Element oneLevelDeep = (Element)itr.next(); | |
| 1400 * List twoLevelsDeep = oneLevelDeep.getChildren(); | |
| 1401 * // Do something with these children | |
| 1402 * } | |
| 1403 * </code> | |
| 1404 * </pre> | |
| 1405 * </p> | |
| 1406 * | |
| 1407 * @return list of child <code>Element</code> objects for this element | |
| 1408 */ | |
| 1409 public List getChildren() { | |
| 1410 return content.getView(new ElementFilter()); | |
| 1411 } | |
| 1412 | |
| 1413 /** | |
| 1414 * This returns a <code>List</code> of all the child elements | |
| 1415 * nested directly (one level deep) within this element with the given | |
| 1416 * local name and belonging to no namespace, returned as | |
| 1417 * <code>Element</code> objects. If this target element has no nested | |
| 1418 * elements with the given name outside a namespace, an empty List | |
| 1419 * is returned. The returned list is "live" in document order | |
| 1420 * and changes to it affect the element's actual contents. | |
| 1421 * <p> | |
| 1422 * Please see the notes for <code>{@link #getChildren}</code> | |
| 1423 * for a code example. | |
| 1424 * </p> | |
| 1425 * | |
| 1426 * @param name local name for the children to match | |
| 1427 * @return all matching child elements | |
| 1428 */ | |
| 1429 public List getChildren(final String name) { | |
| 1430 return getChildren(name, Namespace.NO_NAMESPACE); | |
| 1431 } | |
| 1432 | |
| 1433 /** | |
| 1434 * This returns a <code>List</code> of all the child elements | |
| 1435 * nested directly (one level deep) within this element with the given | |
| 1436 * local name and belonging to the given Namespace, returned as | |
| 1437 * <code>Element</code> objects. If this target element has no nested | |
| 1438 * elements with the given name in the given Namespace, an empty List | |
| 1439 * is returned. The returned list is "live" in document order | |
| 1440 * and changes to it affect the element's actual contents. | |
| 1441 * <p> | |
| 1442 * Please see the notes for <code>{@link #getChildren}</code> | |
| 1443 * for a code example. | |
| 1444 * </p> | |
| 1445 * | |
| 1446 * @param name local name for the children to match | |
| 1447 * @param ns <code>Namespace</code> to search within | |
| 1448 * @return all matching child elements | |
| 1449 */ | |
| 1450 public List getChildren(final String name, final Namespace ns) { | |
| 1451 return content.getView(new ElementFilter(name, ns)); | |
| 1452 } | |
| 1453 | |
| 1454 /** | |
| 1455 * This returns the first child element within this element with the | |
| 1456 * given local name and belonging to the given namespace. | |
| 1457 * If no elements exist for the specified name and namespace, null is | |
| 1458 * returned. | |
| 1459 * | |
| 1460 * @param name local name of child element to match | |
| 1461 * @param ns <code>Namespace</code> to search within | |
| 1462 * @return the first matching child element, or null if not found | |
| 1463 */ | |
| 1464 public Element getChild(final String name, final Namespace ns) { | |
| 1465 final List elements = content.getView(new ElementFilter(name, ns)); | |
| 1466 final Iterator iter = elements.iterator(); | |
| 1467 if (iter.hasNext()) { | |
| 1468 return (Element) iter.next(); | |
| 1469 } | |
| 1470 return null; | |
| 1471 } | |
| 1472 | |
| 1473 /** | |
| 1474 * This returns the first child element within this element with the | |
| 1475 * given local name and belonging to no namespace. | |
| 1476 * If no elements exist for the specified name and namespace, null is | |
| 1477 * returned. | |
| 1478 * | |
| 1479 * @param name local name of child element to match | |
| 1480 * @return the first matching child element, or null if not found | |
| 1481 */ | |
| 1482 public Element getChild(final String name) { | |
| 1483 return getChild(name, Namespace.NO_NAMESPACE); | |
| 1484 } | |
| 1485 | |
| 1486 /** | |
| 1487 * <p> | |
| 1488 * This removes the first child element (one level deep) with the | |
| 1489 * given local name and belonging to no namespace. | |
| 1490 * Returns true if a child was removed. | |
| 1491 * </p> | |
| 1492 * | |
| 1493 * @param name the name of child elements to remove | |
| 1494 * @return whether deletion occurred | |
| 1495 */ | |
| 1496 public boolean removeChild(final String name) { | |
| 1497 return removeChild(name, Namespace.NO_NAMESPACE); | |
| 1498 } | |
| 1499 | |
| 1500 /** | |
| 1501 * <p> | |
| 1502 * This removes the first child element (one level deep) with the | |
| 1503 * given local name and belonging to the given namespace. | |
| 1504 * Returns true if a child was removed. | |
| 1505 * </p> | |
| 1506 * | |
| 1507 * @param name the name of child element to remove | |
| 1508 * @param ns <code>Namespace</code> to search within | |
| 1509 * @return whether deletion occurred | |
| 1510 */ | |
| 1511 public boolean removeChild(final String name, final Namespace ns) { | |
| 1512 final Filter filter = new ElementFilter(name, ns); | |
| 1513 final List old = content.getView(filter); | |
| 1514 final Iterator iter = old.iterator(); | |
| 1515 if (iter.hasNext()) { | |
| 1516 iter.next(); | |
| 1517 iter.remove(); | |
| 1518 return true; | |
| 1519 } | |
| 1520 | |
| 1521 return false; | |
| 1522 } | |
| 1523 | |
| 1524 /** | |
| 1525 * <p> | |
| 1526 * This removes all child elements (one level deep) with the | |
| 1527 * given local name and belonging to no namespace. | |
| 1528 * Returns true if any were removed. | |
| 1529 * </p> | |
| 1530 * | |
| 1531 * @param name the name of child elements to remove | |
| 1532 * @return whether deletion occurred | |
| 1533 */ | |
| 1534 public boolean removeChildren(final String name) { | |
| 1535 return removeChildren(name, Namespace.NO_NAMESPACE); | |
| 1536 } | |
| 1537 | |
| 1538 /** | |
| 1539 * <p> | |
| 1540 * This removes all child elements (one level deep) with the | |
| 1541 * given local name and belonging to the given namespace. | |
| 1542 * Returns true if any were removed. | |
| 1543 * </p> | |
| 1544 * | |
| 1545 * @param name the name of child elements to remove | |
| 1546 * @param ns <code>Namespace</code> to search within | |
| 1547 * @return whether deletion occurred | |
| 1548 */ | |
| 1549 public boolean removeChildren(final String name, final Namespace ns) { | |
| 1550 boolean deletedSome = false; | |
| 1551 | |
| 1552 final Filter filter = new ElementFilter(name, ns); | |
| 1553 final List old = content.getView(filter); | |
| 1554 final Iterator iter = old.iterator(); | |
| 1555 while (iter.hasNext()) { | |
| 1556 iter.next(); | |
| 1557 iter.remove(); | |
| 1558 deletedSome = true; | |
| 1559 } | |
| 1560 | |
| 1561 return deletedSome; | |
| 1562 } | |
| 1563 | |
| 1564 } |
