1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.exolab.castor.xml.util;
36
37 import java.util.Stack;
38
39 import org.exolab.castor.types.AnyNode;
40 import org.exolab.castor.xml.Namespaces;
41 import org.exolab.castor.xml.NamespacesStack;
42 import org.xml.sax.AttributeList;
43 import org.xml.sax.Attributes;
44 import org.xml.sax.ContentHandler;
45 import org.xml.sax.DocumentHandler;
46 import org.xml.sax.ErrorHandler;
47 import org.xml.sax.Locator;
48 import org.xml.sax.SAXException;
49 import org.xml.sax.SAXParseException;
50
51
52
53
54
55
56
57
58 public class SAX2ANY implements ContentHandler, DocumentHandler, ErrorHandler {
59
60
61
62 private final static String XMLNS_PREFIX = "xmlns";
63 private final static int XMLNS_PREFIX_LENGTH = XMLNS_PREFIX.length() + 1;
64
65
66
67
68 private AnyNode _startingNode;
69
70
71
72
73 private AnyNode _node;
74
75
76
77
78 private Stack<AnyNode> _nodeStack = new Stack<>();
79
80
81
82
83 private Stack<AnyNode> _namespaces = new Stack<>();
84
85
86
87
88
89
90 private boolean _processNamespace = true;
91
92
93
94
95 private boolean _character = false;
96
97
98
99
100 private NamespacesStack namespacesStack;
101
102 private boolean _wsPreserve = false;
103
104
105
106
107 public SAX2ANY() {
108 super();
109 init();
110 }
111
112
113
114
115
116
117
118 public SAX2ANY(NamespacesStack namespacesStack, boolean wsPreserve) {
119 this.namespacesStack = namespacesStack;
120 _wsPreserve = wsPreserve;
121 init();
122 }
123
124 private void init() {
125 if (this.namespacesStack == null)
126 this.namespacesStack = new NamespacesStack();
127 }
128
129
130
131
132
133
134 public void setDocumentLocator(final Locator locator) {}
135
136
137
138
139 public void startDocument() throws SAXException {}
140
141 public void endDocument() throws SAXException {}
142
143 public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
144 return;
145 }
146
147 public void processingInstruction(String target, String data) throws SAXException {
148 return;
149 }
150
151 public void skippedEntity(String name) throws SAXException {
152 return;
153 }
154
155
156
157 public void startPrefixMapping(String prefix, String uri) throws SAXException {
158 AnyNode temp = new AnyNode(AnyNode.NAMESPACE, null, prefix, uri, null);
159 _namespaces.push(temp);
160 if (_processNamespace) {
161 namespacesStack.addNewNamespaceScope();
162 _processNamespace = true;
163 }
164 namespacesStack.addNamespace(prefix, uri);
165 }
166
167 public void endPrefixMapping(String prefix) throws SAXException {
168 namespacesStack.removeNamespace(prefix);
169 }
170
171
172
173
174
175 public void startElement(String name, AttributeList atts) throws SAXException {
176 _character = false;
177 String qName;
178 String value;
179 AnyNode tempNode = null;
180
181
182
183
184 namespacesStack.addNewNamespaceScope();
185 String prefix = "";
186 String namespaceURI = null;
187 int idx = name.indexOf(':');
188 if (idx >= 0) {
189 prefix = name.substring(0, idx);
190 }
191 namespaceURI = namespacesStack.getNamespaceURI(prefix);
192
193 for (int i = 0; i < atts.getLength(); ++i) {
194 qName = atts.getName(i);
195 value = atts.getValue(i);
196 String nsPrefix = null;
197
198 if (qName.startsWith(XMLNS_PREFIX)) {
199
200
201 nsPrefix = (qName.equals(XMLNS_PREFIX)) ? null : qName.substring(XMLNS_PREFIX_LENGTH);
202 tempNode = new AnyNode(AnyNode.NAMESPACE, getLocalPart(qName), nsPrefix, value, null);
203 namespacesStack.addNamespace(nsPrefix, value);
204 _namespaces.push(tempNode);
205 if (prefix.equals(nsPrefix))
206 namespaceURI = value;
207 }
208 }
209
210
211 createNodeElement(namespaceURI, getLocalPart(name), name);
212 while (!_namespaces.empty()) {
213 tempNode = (AnyNode) _namespaces.pop();
214 _node.addNamespace(tempNode);
215 }
216
217
218 for (int i = 0; i < atts.getLength(); ++i) {
219
220 qName = atts.getName(i);
221 value = atts.getValue(i);
222
223
224 if (!qName.startsWith(XMLNS_PREFIX)) {
225 tempNode = new AnyNode(AnyNode.ATTRIBUTE, getLocalPart(qName), null, null, value);
226 _node.addAttribute(tempNode);
227 }
228 }
229 tempNode = null;
230 }
231
232
233
234
235 public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
236 throws SAXException {
237 AnyNode tempNode;
238
239
240 if (_processNamespace) {
241
242
243
244 namespacesStack.addNewNamespaceScope();
245 String prefix = "";
246 int idx = qName.indexOf(':');
247 if (idx >= 0) {
248 prefix = qName.substring(0, idx);
249 }
250 namespaceURI = namespacesStack.getNamespaceURI(prefix);
251
252 for (int i = 0; i < atts.getLength(); ++i) {
253 String attrqName = atts.getQName(i);
254 String value = atts.getValue(i);
255 String nsPrefix = null;
256
257 if (attrqName.startsWith(XMLNS_PREFIX)) {
258
259 nsPrefix =
260 (attrqName.equals(XMLNS_PREFIX)) ? null : attrqName.substring(XMLNS_PREFIX_LENGTH);
261 tempNode = new AnyNode(AnyNode.NAMESPACE, getLocalPart(attrqName), nsPrefix, value, null);
262 namespacesStack.addNamespace(nsPrefix, value);
263 _namespaces.push(tempNode);
264 if (prefix.equals(nsPrefix))
265 namespaceURI = value;
266 }
267 }
268
269 }
270
271
272 createNodeElement(namespaceURI, localName, qName);
273
274
275 for (int i = 0; i < atts.getLength(); ++i) {
276
277 String uri = atts.getURI(i);
278 String attqName = atts.getQName(i);
279 String value = atts.getValue(i);
280 String prefix = null;
281
282
283 if (_processNamespace)
284 if (attqName.startsWith(XMLNS_PREFIX))
285 continue;
286
287
288 if ((attqName.length() != 0) && (attqName.indexOf(':') != -1))
289 prefix = attqName.substring(0, attqName.indexOf(':'));
290
291
292 if (_processNamespace) {
293
294 if (prefix != null)
295 uri = namespacesStack.getNamespaceURI(prefix);
296 }
297
298 tempNode = new AnyNode(AnyNode.ATTRIBUTE, getLocalPart(attqName), prefix, uri, value);
299 _node.addAttribute(tempNode);
300 }
301
302
303
304 while (!_namespaces.empty()) {
305 tempNode = (AnyNode) _namespaces.pop();
306 _node.addNamespace(tempNode);
307 }
308 tempNode = null;
309 }
310
311
312 public void endElement(String name) throws SAXException {
313 int idx = name.indexOf(':');
314 String prefix = (idx >= 0) ? name.substring(0, idx) : "";
315 String namespaceURI = namespacesStack.getNamespaceURI(prefix);
316 endElement(namespaceURI, getLocalPart(name), name);
317 namespacesStack.removeNamespaceScope();
318 }
319
320 public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
321 _character = false;
322 String name = null;
323
324
325 if (localName != null && localName.length() > 0) {
326 name = localName;
327 } else {
328 name = getLocalPart(qName);
329 }
330
331
332 if (_startingNode.getLocalName().equals(name) && _nodeStack.empty())
333 return;
334
335
336 _node = (AnyNode) _nodeStack.pop();
337
338
339
340 if (_nodeStack.empty()) {
341 _startingNode.addChild(_node);
342 _node = _startingNode;
343 } else {
344 AnyNode previousNode = (AnyNode) _nodeStack.peek();
345 previousNode.addChild(_node);
346
347 _node = previousNode;
348 }
349 }
350
351 public void characters(char[] ch, int start, int length) throws SAXException {
352
353 String temp = new String(ch, start, length);
354
355 if (isWhitespace(temp) && !_wsPreserve && !_character)
356 return;
357 AnyNode tempNode = new AnyNode(AnyNode.TEXT, null, null, null, temp);
358 _node.addChild(tempNode);
359 _character = true;
360 }
361
362
363
364
365 public void warning(SAXParseException e) throws SAXException {
366 String err = "SAX2ANY warning\n" + "Line : " + e.getLineNumber() + '\n' + "URI : "
367 + e.getSystemId() + '\n' + e.getMessage();
368 throw new SAXException(err, e);
369 }
370
371 public void error(SAXParseException e) throws SAXException {
372 String err = "SAX2ANY Error \n" + "Line : " + e.getLineNumber() + '\n' + "URI : "
373 + e.getSystemId() + '\n' + e.getMessage();
374 throw new SAXException(err, e);
375 }
376
377 public void fatalError(SAXParseException e) throws SAXException {
378 String err = "SAX2ANY Fatal Error \n" + "Line : " + e.getLineNumber() + '\n' + "URI : "
379 + e.getSystemId() + '\n' + e.getMessage();
380 throw new SAXException(err, e);
381 }
382
383
384
385
386 public AnyNode getStartingNode() {
387 return _startingNode;
388 }
389
390
391
392
393
394
395
396 private boolean isWhitespace(String string) {
397 for (int i = 0; i < string.length(); i++) {
398 char ch = string.charAt(i);
399 switch (ch) {
400 case ' ':
401 case '\n':
402 case '\t':
403 case '\r':
404 break;
405 default:
406 return false;
407 }
408 }
409 return true;
410 }
411
412
413
414
415
416
417
418 private String getLocalPart(String ncName) {
419 int idx = ncName.indexOf(':');
420 if (idx >= 0)
421 return ncName.substring(idx + 1);
422 return ncName;
423 }
424
425 private void createNodeElement(String namespaceURI, String localName, String qName) {
426
427 String prefix = null;
428
429 if (namespaceURI != null) {
430 prefix = namespacesStack.getNamespacePrefix(namespaceURI);
431 } else if (qName != null) {
432 if ((qName.length() != 0) && (qName.indexOf(':') != -1))
433 prefix = qName.substring(0, qName.indexOf(':'));
434 }
435
436 String name = null;
437
438
439 if (localName != null && localName.length() > 0)
440 name = localName;
441 else
442 name = getLocalPart(qName);
443
444
445
446 if ((_nodeStack.empty()) && (_startingNode == null)) {
447 _startingNode = new AnyNode(AnyNode.ELEMENT, name, prefix, namespaceURI, null);
448 _node = _startingNode;
449 } else {
450 _node = new AnyNode(AnyNode.ELEMENT, name, prefix, namespaceURI, null);
451
452 _nodeStack.push(_node);
453 }
454 }
455
456 }