001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.jxpath.ri.model.dom;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.apache.commons.jxpath.ri.model.NodeIterator;
023    import org.apache.commons.jxpath.ri.model.NodePointer;
024    import org.w3c.dom.Attr;
025    import org.w3c.dom.Document;
026    import org.w3c.dom.NamedNodeMap;
027    import org.w3c.dom.Node;
028    
029    /**
030     * An iterator of namespaces of a DOM Node.
031     *
032     * @author Dmitri Plotnikov
033     * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
034     */
035    public class DOMNamespaceIterator implements NodeIterator {
036        private NodePointer parent;
037        private List attributes;
038        private int position = 0;
039    
040        /**
041         * Create a new DOMNamespaceIterator.
042         * @param parent parent pointer
043         */
044        public DOMNamespaceIterator(NodePointer parent) {
045            this.parent = parent;
046            attributes = new ArrayList();
047            collectNamespaces(attributes, (Node) parent.getNode());
048        }
049    
050        /**
051         * Collect namespaces from attribute nodes.
052         * @param attributes attribute list
053         * @param node target node
054         */
055        private void collectNamespaces(List attributes, Node node) {
056            Node parent = node.getParentNode();
057            if (parent != null) {
058                collectNamespaces(attributes, parent);
059            }
060            if (node.getNodeType() == Node.DOCUMENT_NODE) {
061                node = ((Document) node).getDocumentElement();
062            }
063            if (node.getNodeType() == Node.ELEMENT_NODE) {
064                NamedNodeMap map = node.getAttributes();
065                int count = map.getLength();
066                for (int i = 0; i < count; i++) {
067                    Attr attr = (Attr) map.item(i);
068                    String prefix = DOMNodePointer.getPrefix(attr);
069                    String name = DOMNodePointer.getLocalName(attr);
070                    if ((prefix != null && prefix.equals("xmlns"))
071                        || (prefix == null && name.equals("xmlns"))) {
072                        attributes.add(attr);
073                    }
074                }
075            }
076        }
077    
078        public NodePointer getNodePointer() {
079            if (position == 0) {
080                if (!setPosition(1)) {
081                    return null;
082                }
083                position = 0;
084            }
085            int index = position - 1;
086            if (index < 0) {
087                index = 0;
088            }
089            String prefix = "";
090            Attr attr = (Attr) attributes.get(index);
091            String name = attr.getPrefix();
092            if (name != null && name.equals("xmlns")) {
093                prefix = DOMNodePointer.getLocalName(attr);
094            }
095            return new NamespacePointer(parent, prefix, attr.getValue());
096        }
097    
098        public int getPosition() {
099            return position;
100        }
101    
102        public boolean setPosition(int position) {
103            this.position = position;
104            return position >= 1 && position <= attributes.size();
105        }
106    }