1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.exolab.castor.xml.parsing;
15
16 import org.apache.commons.lang3.StringUtils;
17 import org.exolab.castor.xml.AttributeSet;
18 import org.exolab.castor.xml.util.AttributeSetImpl;
19 import org.xml.sax.AttributeList;
20 import org.xml.sax.Attributes;
21 import org.xml.sax.SAXException;
22
23
24
25
26
27
28
29
30
31 public class AttributeSetBuilder {
32
33
34
35
36
37 private static final String XML_PREFIX = "xml";
38
39
40
41
42 private static final String XMLNS = "xmlns";
43
44
45
46
47 private final static String XMLNS_PREFIX = "xmlns:";
48
49
50
51
52 private final static int XMLNS_PREFIX_LENGTH = XMLNS_PREFIX.length();
53
54
55
56
57 private NamespaceHandling _namespaceHandling = null;
58
59
60
61
62
63
64 public AttributeSetBuilder(NamespaceHandling namespaceHandling) {
65 super();
66 _namespaceHandling = namespaceHandling;
67 }
68
69
70
71
72
73
74 private AttributeSetImpl prepareAttributeSetImpl(Attributes atts) {
75 if (atts != null) {
76 return new AttributeSetImpl(atts.getLength());
77 }
78 return new AttributeSetImpl();
79 }
80
81
82
83
84
85
86
87
88 public AttributeSet getAttributeSet(Attributes atts) throws SAXException {
89 AttributeSetImpl attributeSet = prepareAttributeSetImpl(atts);
90 return processAttributes(atts, attributeSet);
91 }
92
93
94
95
96
97
98
99
100 private AttributeSet processAttributes(Attributes atts, AttributeSetImpl attributeSet) {
101
102
103 if (atts == null || atts.getLength() == 0) {
104 return attributeSet;
105 }
106
107 boolean hasQNameAtts = false;
108
109
110
111 for (int i = 0; i < atts.getLength(); i++) {
112 String attName = atts.getQName(i);
113 if (StringUtils.isNotEmpty(attName)) {
114 if (!attName.equals(XMLNS) && !attName.startsWith(XMLNS_PREFIX)) {
115
116 if (attName.indexOf(':') < 0) {
117 attributeSet.setAttribute(attName, atts.getValue(i), atts.getURI(i));
118 } else
119 hasQNameAtts = true;
120 }
121 } else {
122
123
124 attName = atts.getLocalName(i);
125 if (!XMLNS.equals(attName)) {
126 attributeSet.setAttribute(attName, atts.getValue(i), atts.getURI(i));
127 }
128 }
129 }
130
131
132 if (!hasQNameAtts) {
133 return attributeSet;
134 }
135
136 for (int i = 0; i < atts.getLength(); i++) {
137 String attName = atts.getQName(i);
138 if (StringUtils.isNotEmpty(attName)) {
139
140 if ((!attName.equals(XMLNS)) && (!attName.startsWith(XMLNS_PREFIX))) {
141 int idx = attName.indexOf(':');
142 if (idx >= 0) {
143 String prefix = attName.substring(0, idx);
144 attName = attName.substring(idx + 1);
145 String nsURI = atts.getURI(i);
146 if (StringUtils.isEmpty(nsURI)) {
147 nsURI = _namespaceHandling.getNamespaceURI(prefix);
148 }
149 attributeSet.setAttribute(attName, atts.getValue(i), nsURI);
150 }
151 }
152 }
153
154 }
155 return attributeSet;
156 }
157
158
159
160
161
162
163
164
165
166
167 public AttributeSet getAttributeSet(AttributeList atts) throws SAXException {
168 AttributeSetImpl attributeSet = prepareAttributeSetImpl(atts);
169 return processAttributeList(atts, attributeSet);
170 }
171
172
173
174
175
176
177
178
179
180 private AttributeSet processAttributeList(AttributeList atts, AttributeSetImpl attributeSet)
181 throws SAXException {
182 if (atts == null || atts.getLength() == 0)
183 return attributeSet;
184
185
186 int attCount = 0;
187 boolean[] validAtts = new boolean[atts.getLength()];
188 for (int i = 0; i < validAtts.length; i++) {
189 String attName = atts.getName(i);
190 if (attName.equals(XMLNS)) {
191 _namespaceHandling.addDefaultNamespace(atts.getValue(i));
192 } else if (attName.startsWith(XMLNS_PREFIX)) {
193 String prefix = attName.substring(XMLNS_PREFIX_LENGTH);
194 _namespaceHandling.addNamespace(prefix, atts.getValue(i));
195 } else {
196 validAtts[i] = true;
197 ++attCount;
198 }
199 }
200
201 for (int i = 0; i < validAtts.length; i++) {
202 if (!validAtts[i])
203 continue;
204 String namespace = null;
205 String attName = atts.getName(i);
206 int idx = attName.indexOf(':');
207 if (idx > 0) {
208 String prefix = attName.substring(0, idx);
209 if (!prefix.equals(XML_PREFIX)) {
210 attName = attName.substring(idx + 1);
211 namespace = _namespaceHandling.getNamespaceURI(prefix);
212 if (namespace == null) {
213 String error = "The namespace associated with " + "the prefix '" + prefix
214 + "' could not be resolved.";
215 throw new SAXException(error);
216
217 }
218 }
219 }
220 attributeSet.setAttribute(attName, atts.getValue(i), namespace);
221 }
222 return attributeSet;
223 }
224
225
226
227
228
229
230
231
232 private AttributeSetImpl prepareAttributeSetImpl(AttributeList atts) {
233 if (atts == null) {
234 return new AttributeSetImpl();
235 }
236 return new AttributeSetImpl(atts.getLength());
237 }
238 }