1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.exolab.castor.xml.util;
15
16 import org.castor.core.util.Assert;
17 import org.exolab.castor.xml.Namespaces;
18 import org.exolab.castor.xml.NamespacesStack;
19 import org.xml.sax.Attributes;
20 import org.xml.sax.SAXException;
21 import org.xml.sax.helpers.DefaultHandler;
22
23 import javax.xml.namespace.QName;
24 import javax.xml.stream.XMLEventFactory;
25 import javax.xml.stream.XMLEventWriter;
26 import javax.xml.stream.XMLStreamException;
27 import javax.xml.stream.events.Attribute;
28 import javax.xml.stream.events.Namespace;
29 import java.util.Enumeration;
30 import java.util.Iterator;
31
32
33
34
35
36
37
38
39
40 public class StaxEventHandler extends DefaultHandler {
41
42
43
44
45 private final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
46
47
48
49
50 private final XMLEventWriter xmlEventWriter;
51
52
53
54
55 private NamespacesStack namespacesStack = new NamespacesStack();
56
57
58
59
60 private boolean createNamespaceScope = true;
61
62
63
64
65
66
67
68
69 public StaxEventHandler(XMLEventWriter xmlEventWriter) {
70 Assert.paramNotNull(xmlEventWriter, "xmlEventWriter");
71
72 this.xmlEventWriter = xmlEventWriter;
73 }
74
75 @Override
76 public void startDocument() throws SAXException {
77 try {
78
79 xmlEventWriter.add(eventFactory.createStartDocument());
80 } catch (XMLStreamException e) {
81 convertToSAXException("Error occurred when writing document start.", e);
82 }
83 }
84
85 @Override
86 public void endDocument() throws SAXException {
87 try {
88
89 xmlEventWriter.add(eventFactory.createEndDocument());
90 } catch (XMLStreamException e) {
91 convertToSAXException("Error occurred when writing document end.", e);
92 }
93 }
94
95 @Override
96 public void startPrefixMapping(String prefix, String uri) throws SAXException {
97 if (createNamespaceScope) {
98 namespacesStack.addNewNamespaceScope();
99 createNamespaceScope = false;
100 }
101
102 namespacesStack.addNamespace(prefix, uri);
103 }
104
105 @Override
106 public void startElement(String uri, String localName, String qName, Attributes attributes)
107 throws SAXException {
108 try {
109
110 xmlEventWriter.add(eventFactory.createStartElement(new QName(qName),
111 new AttributeIterator(attributes), new NamespaceIterator(namespacesStack)));
112 } catch (XMLStreamException e) {
113 convertToSAXException("Error occurred when writing element start.", e);
114 }
115 }
116
117 @Override
118 public void endElement(String uri, String localName, String qName) throws SAXException {
119 try {
120
121 xmlEventWriter.add(eventFactory.createEndElement(new QName(qName), null));
122 } catch (XMLStreamException e) {
123 convertToSAXException("Error occurred when writing element end.", e);
124 }
125 }
126
127 @Override
128 public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
129 try {
130
131 xmlEventWriter.add(eventFactory.createCharacters(new String(ch, start, length)));
132 } catch (XMLStreamException e) {
133 convertToSAXException("Error occurred when writing white spaces.", e);
134 }
135 }
136
137 @Override
138 public void characters(char[] ch, int start, int length) throws SAXException {
139 try {
140
141 xmlEventWriter.add(eventFactory.createCharacters(new String(ch, start, length)));
142 } catch (XMLStreamException e) {
143 convertToSAXException("Error occurred when writing characters.", e);
144 }
145 }
146
147 @Override
148 public void processingInstruction(String target, String data) throws SAXException {
149 try {
150
151 xmlEventWriter.add(eventFactory.createProcessingInstruction(target, data));
152 } catch (XMLStreamException e) {
153 convertToSAXException("Error occurred when writing processing instruction.", e);
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166 private void convertToSAXException(String msg, XMLStreamException e) throws SAXException {
167 throw new SAXException(msg, e);
168 }
169
170
171
172
173
174
175
176
177 private class AttributeIterator implements Iterator {
178
179
180
181
182 private final Attributes attributes;
183
184
185
186
187 private int index;
188
189
190
191
192
193
194 private AttributeIterator(Attributes attributes) {
195 this.attributes = attributes;
196 }
197
198 public boolean hasNext() {
199 return index < attributes.getLength();
200 }
201
202 public Object next() {
203
204 Attribute attribute =
205 eventFactory.createAttribute(attributes.getQName(index), attributes.getValue(index));
206
207 index++;
208
209 return attribute;
210 }
211
212 public void remove() {
213 throw new UnsupportedOperationException("Method 'remove' is not supported.");
214 }
215 }
216
217
218
219
220
221
222
223
224
225 private class NamespaceIterator implements Iterator<Namespace> {
226
227
228
229
230 private final NamespacesStack namespaces;
231
232
233
234
235 private final Enumeration namespaceEnumerator;
236
237
238
239
240 private boolean hasDefaultNamespace;
241
242
243
244
245 private boolean defaultNamespaceWritten;
246
247
248
249
250
251
252 private NamespaceIterator(NamespacesStack namespaces) {
253 this.namespaces = namespaces;
254 this.namespaceEnumerator = namespaces.getLocalNamespacePrefixes();
255
256
257 String defaultNamespace = namespaces.getDefaultNamespaceURI();
258 if (defaultNamespace != null && defaultNamespace.length() > 0) {
259 hasDefaultNamespace = true;
260 }
261 }
262
263 public boolean hasNext() {
264 return hasDefaultNamespace && !defaultNamespaceWritten
265 || namespaceEnumerator.hasMoreElements();
266 }
267
268 public Namespace next() {
269 Namespace namespace;
270
271
272 if (hasDefaultNamespace && !defaultNamespaceWritten) {
273
274
275 namespace = eventFactory.createNamespace(namespaces.getDefaultNamespaceURI());
276 defaultNamespaceWritten = true;
277 } else {
278
279
280 String prefix = (String) namespaceEnumerator.nextElement();
281 namespace = eventFactory.createNamespace(prefix, namespaces.getNamespaceURI(prefix));
282 }
283
284
285 return namespace;
286 }
287
288 public void remove() {
289 throw new UnsupportedOperationException("Method 'remove' is not supported.");
290 }
291 }
292 }