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