1
2
3
4
5
6
7
8
9
10 package org.dom4j.dom;
11
12 import java.util.List;
13
14 import org.dom4j.Branch;
15 import org.dom4j.CharacterData;
16 import org.dom4j.Document;
17 import org.dom4j.DocumentType;
18 import org.dom4j.Element;
19 import org.dom4j.Node;
20 import org.w3c.dom.DOMException;
21 import org.w3c.dom.NamedNodeMap;
22 import org.w3c.dom.NodeList;
23
24 /*** <p><code>DOMNodeHelper</code> contains a collection of utility methods
25 * for use across Node implementations.</p>
26 *
27 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
28 * @version $Revision: 1.18 $
29 */
30 public class DOMNodeHelper {
31
32 public static final NodeList EMPTY_NODE_LIST = new EmptyNodeList();
33
34 public static class EmptyNodeList implements NodeList {
35 public org.w3c.dom.Node item(int index) {
36 return null;
37 }
38 public int getLength() {
39 return 0;
40 }
41 }
42
43
44
45
46 public static boolean supports(Node node, String feature, String version) {
47 return false;
48 }
49
50 public static String getNamespaceURI(Node node) {
51 return null;
52 }
53
54 public static String getPrefix(Node node) {
55 return null;
56 }
57
58 public static String getLocalName(Node node) {
59 return null;
60 }
61
62 public static void setPrefix(Node node, String prefix) throws DOMException {
63 notSupported();
64 }
65
66 public static String getNodeValue(Node node) throws DOMException {
67 return node.getText();
68 }
69
70 public static void setNodeValue(Node node, String nodeValue) throws DOMException {
71 node.setText(nodeValue);
72 }
73
74 public static org.w3c.dom.Node getParentNode(Node node) {
75 return asDOMNode( node.getParent() );
76 }
77
78 public static NodeList getChildNodes(Node node) {
79 return EMPTY_NODE_LIST;
80 }
81
82 public static org.w3c.dom.Node getFirstChild(Node node) {
83 return null;
84 }
85
86 public static org.w3c.dom.Node getLastChild(Node node) {
87 return null;
88 }
89
90 public static org.w3c.dom.Node getPreviousSibling(Node node) {
91 Element parent = node.getParent();
92 if ( parent != null ) {
93 int index = parent.indexOf( node );
94 if ( index > 0 ) {
95 Node previous = parent.node(index - 1);
96 return asDOMNode( previous );
97 }
98 }
99 return null;
100 }
101
102 public static org.w3c.dom.Node getNextSibling(Node node) {
103 Element parent = node.getParent();
104 if ( parent != null ) {
105 int index = parent.indexOf( node );
106 if ( index >= 0 ) {
107 if ( ++index < parent.nodeCount() ) {
108 Node next = parent.node(index);
109 return asDOMNode( next );
110 }
111 }
112 }
113 return null;
114 }
115
116 public static NamedNodeMap getAttributes(Node node) {
117 return null;
118 }
119
120 public static org.w3c.dom.Document getOwnerDocument(Node node) {
121 return asDOMDocument( node.getDocument() );
122 }
123
124 public static org.w3c.dom.Node insertBefore(
125 Node node,
126 org.w3c.dom.Node newChild,
127 org.w3c.dom.Node refChild
128 ) throws DOMException {
129 if ( node instanceof Branch ) {
130 Branch branch = (Branch) node;
131 List list = branch.content();
132 int index = list.indexOf(refChild);
133 if ( index < 0 ) {
134 branch.add((Node) newChild);
135 }
136 else {
137 list.add(index, newChild);
138 }
139 return newChild;
140 }
141 else {
142 throw new DOMException( DOMException.HIERARCHY_REQUEST_ERR, "Children not allowed for this node: " + node );
143 }
144 }
145
146 public static org.w3c.dom.Node replaceChild(
147 Node node,
148 org.w3c.dom.Node newChild,
149 org.w3c.dom.Node oldChild
150 ) throws DOMException {
151 if ( node instanceof Branch ) {
152 Branch branch = (Branch) node;
153 List list = branch.content();
154 int index = list.indexOf(oldChild);
155 if ( index < 0 ) {
156 throw new DOMException( DOMException.NOT_FOUND_ERR, "Tried to replace a non existing child for node: " + node );
157 }
158 list.set(index, newChild);
159 return oldChild;
160 }
161 else {
162 throw new DOMException( DOMException.HIERARCHY_REQUEST_ERR, "Children not allowed for this node: " + node );
163 }
164 }
165
166 public static org.w3c.dom.Node removeChild(
167 Node node,
168 org.w3c.dom.Node oldChild
169 ) throws DOMException {
170 if ( node instanceof Branch ) {
171 Branch branch = (Branch) node;
172 branch.remove((Node) oldChild);
173 return oldChild;
174 }
175 throw new DOMException( DOMException.HIERARCHY_REQUEST_ERR, "Children not allowed for this node: " + node );
176 }
177
178 public static org.w3c.dom.Node appendChild(
179 Node node,
180 org.w3c.dom.Node newChild
181 ) throws DOMException {
182 if ( node instanceof Branch ) {
183 Branch branch = (Branch) node;
184 org.w3c.dom.Node previousParent = newChild.getParentNode();
185 if (previousParent != null) {
186 previousParent.removeChild(newChild);
187 }
188 branch.add( (Node) newChild );
189 return newChild;
190 }
191 throw new DOMException( DOMException.HIERARCHY_REQUEST_ERR, "Children not allowed for this node: " + node );
192 }
193
194 public static boolean hasChildNodes(Node node) {
195 return false;
196 }
197
198 public static org.w3c.dom.Node cloneNode(Node node, boolean deep) {
199 return asDOMNode( (Node) node.clone() );
200 }
201
202 public static void normalize(Node node) {
203 notSupported();
204 }
205
206 public static boolean isSupported(Node node, String feature, String version) {
207 return false;
208 }
209
210 public static boolean hasAttributes(Node node) {
211 if (node != null && node instanceof Element) {
212 return ((Element) node).attributeCount() > 0;
213 } else {
214 return false;
215 }
216 }
217
218
219
220
221
222 public static String getData(CharacterData charData) throws DOMException {
223 return charData.getText();
224 }
225
226 public static void setData(CharacterData charData, String data) throws DOMException {
227 charData.setText(data);
228 }
229
230 public static int getLength(CharacterData charData) {
231 String text = charData.getText();
232 return ( text != null ) ? text.length() : 0;
233 }
234
235 public static String substringData(
236 CharacterData charData, int offset, int count
237 ) throws DOMException {
238 if (count < 0) {
239 throw new DOMException(
240 DOMException.INDEX_SIZE_ERR,
241 "Illegal value for count: " + count
242 );
243 }
244 String text = charData.getText();
245 int length = ( text != null ) ? text.length() : 0;
246 if ( offset < 0 || offset >= length ) {
247 throw new DOMException(
248 DOMException.INDEX_SIZE_ERR,
249 "No text at offset: " + offset
250 );
251 }
252 if (offset + count > length) {
253 return text.substring(offset);
254 }
255 return text.substring( offset, offset + count );
256 }
257
258 public static void appendData(
259 CharacterData charData, String arg
260 ) throws DOMException {
261 if ( charData.isReadOnly() ) {
262 throw new DOMException(
263 DOMException.NO_MODIFICATION_ALLOWED_ERR,
264 "CharacterData node is read only: " + charData
265 );
266 }
267 else {
268 String text = charData.getText();
269 if ( text == null ) {
270 charData.setText( text );
271 }
272 else {
273 charData.setText( text + arg );
274 }
275 }
276 }
277
278 public static void insertData(CharacterData charData, int offset, String arg) throws DOMException {
279 if ( charData.isReadOnly() ) {
280 throw new DOMException(
281 DOMException.NO_MODIFICATION_ALLOWED_ERR,
282 "CharacterData node is read only: " + charData
283 );
284 }
285 else {
286 String text = charData.getText();
287 if ( text == null ) {
288 charData.setText( arg );
289 }
290 else {
291 int length = text.length();
292 if ( offset < 0 || offset > length ) {
293 throw new DOMException(
294 DOMException.INDEX_SIZE_ERR,
295 "No text at offset: " + offset
296 );
297 }
298 else {
299 StringBuffer buffer = new StringBuffer( text );
300 buffer.insert( offset, arg );
301 charData.setText( buffer.toString() );
302 }
303 }
304 }
305 }
306
307 public static void deleteData(CharacterData charData, int offset, int count) throws DOMException {
308 if ( charData.isReadOnly() ) {
309 throw new DOMException(
310 DOMException.NO_MODIFICATION_ALLOWED_ERR,
311 "CharacterData node is read only: " + charData
312 );
313 }
314 else {
315 if (count < 0) {
316 throw new DOMException(
317 DOMException.INDEX_SIZE_ERR,
318 "Illegal value for count: " + count
319 );
320 }
321 String text = charData.getText();
322 if ( text != null ) {
323 int length = text.length();
324 if ( offset < 0 || offset >= length ) {
325 throw new DOMException(
326 DOMException.INDEX_SIZE_ERR,
327 "No text at offset: " + offset
328 );
329 }
330 else {
331 StringBuffer buffer = new StringBuffer( text );
332 buffer.delete( offset, offset + count );
333 charData.setText( buffer.toString() );
334 }
335 }
336 }
337 }
338
339 public static void replaceData(
340 CharacterData charData, int offset, int count, String arg
341 ) throws DOMException {
342 if ( charData.isReadOnly() ) {
343 throw new DOMException(
344 DOMException.NO_MODIFICATION_ALLOWED_ERR,
345 "CharacterData node is read only: " + charData
346 );
347 }
348 else {
349 if (count < 0) {
350 throw new DOMException(
351 DOMException.INDEX_SIZE_ERR,
352 "Illegal value for count: " + count
353 );
354 }
355 String text = charData.getText();
356 if ( text != null ) {
357 int length = text.length();
358 if ( offset < 0 || offset >= length ) {
359 throw new DOMException(
360 DOMException.INDEX_SIZE_ERR,
361 "No text at offset: " + offset
362 );
363 }
364 else {
365 StringBuffer buffer = new StringBuffer( text );
366 buffer.replace( offset, offset + count, arg );
367 charData.setText( buffer.toString() );
368 }
369 }
370 }
371 }
372
373
374
375
376
377 public static void appendElementsByTagName(
378 List list, Branch parent, String name
379 ) {
380 final boolean isStar = "*".equals(name);
381 for ( int i = 0, size = parent.nodeCount(); i < size; i++ ) {
382 Node node = parent.node(i);
383 if ( node instanceof Element ) {
384 Element element = (Element) node;
385 if ( isStar || name.equals( element.getName() ) ) {
386 list.add( element );
387 }
388 appendElementsByTagName(list, element, name);
389 }
390 }
391 }
392
393 public static void appendElementsByTagNameNS(
394 List list, Branch parent, String namespaceURI, String localName
395 ) {
396 final boolean isStarNS = "*".equals(namespaceURI);
397 final boolean isStarName = "*".equals(localName);
398 for ( int i = 0, size = parent.nodeCount(); i < size; i++ ) {
399 Node node = parent.node(i);
400 if ( node instanceof Element ) {
401 Element element = (Element) node;
402 if ( ( (isStarNS ||
403 ((namespaceURI == null || namespaceURI.length() == 0) &&
404 (element.getNamespaceURI() == null || element.getNamespaceURI().length() == 0)) ||
405 (namespaceURI != null && namespaceURI.equals( element.getNamespaceURI() ))))
406 && (isStarName || localName.equals( element.getName() )) ) {
407 list.add( element );
408 }
409 appendElementsByTagNameNS(list, element, namespaceURI, localName);
410 }
411 }
412 }
413
414
415
416
417
418 public static NodeList createNodeList( final List list ) {
419 return new NodeList() {
420 public org.w3c.dom.Node item(int index) {
421 if (index >= getLength()) {
422
423
424
425
426
427 return null;
428 } else {
429 return DOMNodeHelper.asDOMNode( (Node) list.get( index ) );
430 }
431 }
432 public int getLength() {
433 return list.size();
434 }
435 };
436 }
437
438 public static org.w3c.dom.Node asDOMNode(Node node) {
439 if ( node == null ) {
440 return null;
441 }
442 if ( node instanceof org.w3c.dom.Node ) {
443 return (org.w3c.dom.Node) node;
444 }
445 else {
446
447 System.out.println( "Cannot convert: " + node + " into a W3C DOM Node");
448 notSupported();
449 return null;
450 }
451 }
452
453 public static org.w3c.dom.Document asDOMDocument(Document document) {
454 if ( document == null ) {
455 return null;
456 }
457 if ( document instanceof org.w3c.dom.Document ) {
458 return (org.w3c.dom.Document) document;
459 }
460 else {
461
462 notSupported();
463 return null;
464 }
465 }
466
467 public static org.w3c.dom.DocumentType asDOMDocumentType(DocumentType documentType) {
468 if ( documentType == null ) {
469 return null;
470 }
471 if ( documentType instanceof org.w3c.dom.DocumentType ) {
472 return (org.w3c.dom.DocumentType) documentType;
473 }
474 else {
475
476 notSupported();
477 return null;
478 }
479 }
480
481 public static org.w3c.dom.Text asDOMText(CharacterData text) {
482 if ( text == null ) {
483 return null;
484 }
485 if ( text instanceof org.w3c.dom.Text ) {
486 return (org.w3c.dom.Text) text;
487 }
488 else {
489
490 notSupported();
491 return null;
492 }
493 }
494
495 public static org.w3c.dom.Element asDOMElement(Node element) {
496 if ( element == null ) {
497 return null;
498 }
499 if ( element instanceof org.w3c.dom.Element ) {
500 return (org.w3c.dom.Element) element;
501 }
502 else {
503
504 notSupported();
505 return null;
506 }
507 }
508
509 public static org.w3c.dom.Attr asDOMAttr(Node attribute) {
510 if ( attribute == null ) {
511 return null;
512 }
513 if ( attribute instanceof org.w3c.dom.Attr ) {
514 return (org.w3c.dom.Attr) attribute;
515 }
516 else {
517
518 notSupported();
519 return null;
520 }
521 }
522
523 /*** Called when a method has not been implemented yet
524 */
525 public static void notSupported() {
526 throw new DOMException( DOMException.NOT_SUPPORTED_ERR, "Not supported yet");
527 }
528
529 }
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577