1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.ri.model.dom;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Objects;
23
24 import org.apache.commons.jxpath.ri.QName;
25 import org.apache.commons.jxpath.ri.model.NodeIterator;
26 import org.apache.commons.jxpath.ri.model.NodePointer;
27 import org.w3c.dom.Attr;
28 import org.w3c.dom.Element;
29 import org.w3c.dom.NamedNodeMap;
30 import org.w3c.dom.Node;
31
32
33
34
35 public class DOMAttributeIterator implements NodeIterator {
36
37 private final NodePointer parent;
38 private final QName qName;
39 private final List<Attr> attributes;
40 private int position;
41
42
43
44
45
46
47
48 public DOMAttributeIterator(final NodePointer parent, final QName qName) {
49 this.parent = parent;
50 this.qName = qName;
51 attributes = new ArrayList<>();
52 final Node node = (Node) parent.getNode();
53 if (node.getNodeType() == Node.ELEMENT_NODE) {
54 final String lname = qName.getName();
55 if (!lname.equals("*")) {
56 final Attr attr = getAttribute((Element) node, qName);
57 if (attr != null) {
58 attributes.add(attr);
59 }
60 } else {
61 final NamedNodeMap map = node.getAttributes();
62 final int count = map.getLength();
63 for (int i = 0; i < count; i++) {
64 final Attr attr = (Attr) map.item(i);
65 if (testAttr(attr)) {
66 attributes.add(attr);
67 }
68 }
69 }
70 }
71 }
72
73
74
75
76
77
78
79
80 private Attr getAttribute(final Element element, final QName qName) {
81 final String testPrefix = qName.getPrefix();
82 String testNS = null;
83 if (testPrefix != null) {
84 testNS = parent.getNamespaceResolver().getNamespaceURI(testPrefix);
85 }
86 if (testNS != null) {
87 Attr attr = element.getAttributeNodeNS(testNS, qName.getName());
88 if (attr != null) {
89 return attr;
90 }
91
92
93
94 final NamedNodeMap nnm = element.getAttributes();
95 for (int i = 0; i < nnm.getLength(); i++) {
96 attr = (Attr) nnm.item(i);
97 if (testAttr(attr)) {
98 return attr;
99 }
100 }
101 return null;
102 }
103 return element.getAttributeNode(qName.getName());
104 }
105
106 @Override
107 public NodePointer getNodePointer() {
108 if (position == 0) {
109 if (!setPosition(1)) {
110 return null;
111 }
112 position = 0;
113 }
114 int index = position - 1;
115 if (index < 0) {
116 index = 0;
117 }
118 return new DOMAttributePointer(parent, attributes.get(index));
119 }
120
121 @Override
122 public int getPosition() {
123 return position;
124 }
125
126 @Override
127 public boolean setPosition(final int position) {
128 this.position = position;
129 return position >= 1 && position <= attributes.size();
130 }
131
132
133
134
135
136
137
138 private boolean testAttr(final Attr attr) {
139 final String nodePrefix = DOMNodePointer.getPrefix(attr);
140 final String nodeLocalName = DOMNodePointer.getLocalName(attr);
141 if (nodePrefix != null && nodePrefix.equals("xmlns")) {
142 return false;
143 }
144 if (nodePrefix == null && nodeLocalName.equals("xmlns")) {
145 return false;
146 }
147 final String testLocalName = qName.getName();
148 if (testLocalName.equals("*") || testLocalName.equals(nodeLocalName)) {
149 final String testPrefix = qName.getPrefix();
150 if (testPrefix == null || Objects.equals(testPrefix, nodePrefix)) {
151 return true;
152 }
153 if (nodePrefix == null) {
154 return false;
155 }
156 return Objects.equals(parent.getNamespaceURI(testPrefix), parent.getNamespaceURI(nodePrefix));
157 }
158 return false;
159 }
160 }