View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jxpath.ri.model.dom;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import org.apache.commons.jxpath.ri.model.NodeIterator;
24  import org.apache.commons.jxpath.ri.model.NodePointer;
25  import org.w3c.dom.Attr;
26  import org.w3c.dom.Document;
27  import org.w3c.dom.NamedNodeMap;
28  import org.w3c.dom.Node;
29  
30  /**
31   * An iterator of namespaces of a DOM Node.
32   */
33  public class DOMNamespaceIterator implements NodeIterator {
34  
35      private final NodePointer parent;
36      private final List<Attr> attributes;
37      private int position;
38  
39      /**
40       * Constructs a new DOMNamespaceIterator.
41       *
42       * @param parent parent pointer
43       */
44      public DOMNamespaceIterator(final NodePointer parent) {
45          this.parent = parent;
46          attributes = new ArrayList<>();
47          collectNamespaces(attributes, (Node) parent.getNode());
48      }
49  
50      /**
51       * Collect namespaces from attribute nodes.
52       *
53       * @param attributes attribute list
54       * @param node       target node
55       */
56      private void collectNamespaces(final List<Attr> attributes, Node node) {
57          final Node parent = node.getParentNode();
58          if (parent != null) {
59              collectNamespaces(attributes, parent);
60          }
61          if (node.getNodeType() == Node.DOCUMENT_NODE) {
62              node = ((Document) node).getDocumentElement();
63          }
64          if (node.getNodeType() == Node.ELEMENT_NODE) {
65              final NamedNodeMap map = node.getAttributes();
66              final int count = map.getLength();
67              for (int i = 0; i < count; i++) {
68                  final Attr attr = (Attr) map.item(i);
69                  final String prefix = DOMNodePointer.getPrefix(attr);
70                  final String name = DOMNodePointer.getLocalName(attr);
71                  if (prefix != null && prefix.equals("xmlns") || prefix == null && name.equals("xmlns")) {
72                      attributes.add(attr);
73                  }
74              }
75          }
76      }
77  
78      @Override
79      public NodePointer getNodePointer() {
80          if (position == 0) {
81              if (!setPosition(1)) {
82                  return null;
83              }
84              position = 0;
85          }
86          int index = position - 1;
87          if (index < 0) {
88              index = 0;
89          }
90          String prefix = "";
91          final Attr attr = attributes.get(index);
92          final String name = attr.getPrefix();
93          if (name != null && name.equals("xmlns")) {
94              prefix = DOMNodePointer.getLocalName(attr);
95          }
96          return new NamespacePointer(parent, prefix, attr.getValue());
97      }
98  
99      @Override
100     public int getPosition() {
101         return position;
102     }
103 
104     @Override
105     public boolean setPosition(final int position) {
106         this.position = position;
107         return position >= 1 && position <= attributes.size();
108     }
109 }