1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.jxpath.ri.model.dom;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. import org.apache.commons.jxpath.ri.QName;
  20. import org.apache.commons.jxpath.ri.model.NodeIterator;
  21. import org.apache.commons.jxpath.ri.model.NodePointer;
  22. import org.w3c.dom.Attr;
  23. import org.w3c.dom.Element;
  24. import org.w3c.dom.NamedNodeMap;
  25. import org.w3c.dom.Node;
  26. /**
  27. * An iterator of attributes of a DOM Node.
  28. *
  29. * @author Dmitri Plotnikov
  30. * @version $Revision: 1.11 $ $Date: 2004/02/29 14:17:44 $
  31. */
  32. public class DOMAttributeIterator implements NodeIterator {
  33. private NodePointer parent;
  34. private QName name;
  35. private List attributes;
  36. private int position = 0;
  37. public DOMAttributeIterator(NodePointer parent, QName name) {
  38. this.parent = parent;
  39. this.name = name;
  40. attributes = new ArrayList();
  41. Node node = (Node) parent.getNode();
  42. if (node.getNodeType() == Node.ELEMENT_NODE) {
  43. String lname = name.getName();
  44. if (!lname.equals("*")) {
  45. Attr attr = getAttribute((Element) node, name);
  46. if (attr != null) {
  47. attributes.add(attr);
  48. }
  49. }
  50. else {
  51. NamedNodeMap map = node.getAttributes();
  52. int count = map.getLength();
  53. for (int i = 0; i < count; i++) {
  54. Attr attr = (Attr) map.item(i);
  55. if (testAttr(attr, name)) {
  56. attributes.add(attr);
  57. }
  58. }
  59. }
  60. }
  61. }
  62. private boolean testAttr(Attr attr, QName testName) {
  63. String nodePrefix = DOMNodePointer.getPrefix(attr);
  64. String nodeLocalName = DOMNodePointer.getLocalName(attr);
  65. if (nodePrefix != null && nodePrefix.equals("xmlns")) {
  66. return false;
  67. }
  68. if (nodePrefix == null && nodeLocalName.equals("xmlns")) {
  69. return false;
  70. }
  71. String testLocalName = name.getName();
  72. if (testLocalName.equals("*") || testLocalName.equals(nodeLocalName)) {
  73. String testPrefix = testName.getPrefix();
  74. if (equalStrings(testPrefix, nodePrefix)) {
  75. return true;
  76. }
  77. String testNS = null;
  78. if (testPrefix != null) {
  79. testNS = parent.getNamespaceURI(testPrefix);
  80. }
  81. String nodeNS = null;
  82. if (nodePrefix != null) {
  83. nodeNS = parent.getNamespaceURI(nodePrefix);
  84. }
  85. return equalStrings(testNS, nodeNS);
  86. }
  87. return false;
  88. }
  89. private static boolean equalStrings(String s1, String s2) {
  90. if (s1 == null && s2 != null) {
  91. return false;
  92. }
  93. if (s1 != null && !s1.equals(s2)) {
  94. return false;
  95. }
  96. return true;
  97. }
  98. private Attr getAttribute(Element element, QName name) {
  99. String testPrefix = name.getPrefix();
  100. String testNS = null;
  101. if (testPrefix != null) {
  102. testNS = parent.getNamespaceURI(testPrefix);
  103. }
  104. if (testNS != null) {
  105. Attr attr = element.getAttributeNodeNS(testNS, name.getName());
  106. if (attr != null) {
  107. return attr;
  108. }
  109. // This may mean that the parser does not support NS for
  110. // attributes, example - the version of Crimson bundled
  111. // with JDK 1.4.0
  112. NamedNodeMap nnm = element.getAttributes();
  113. for (int i = 0; i < nnm.getLength(); i++) {
  114. attr = (Attr) nnm.item(i);
  115. if (testAttr(attr, name)) {
  116. return attr;
  117. }
  118. }
  119. return null;
  120. }
  121. else {
  122. return element.getAttributeNode(name.getName());
  123. }
  124. }
  125. public NodePointer getNodePointer() {
  126. if (position == 0) {
  127. if (!setPosition(1)) {
  128. return null;
  129. }
  130. position = 0;
  131. }
  132. int index = position - 1;
  133. if (index < 0) {
  134. index = 0;
  135. }
  136. return new DOMAttributePointer(parent, (Attr) attributes.get(index));
  137. }
  138. public int getPosition() {
  139. return position;
  140. }
  141. public boolean setPosition(int position) {
  142. this.position = position;
  143. return position >= 1 && position <= attributes.size();
  144. }
  145. }