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 } |