1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.xml.stream;
18
19 import java.util.Iterator;
20 import javax.xml.namespace.QName;
21 import javax.xml.stream.XMLEventReader;
22 import javax.xml.stream.XMLStreamConstants;
23 import javax.xml.stream.XMLStreamException;
24 import javax.xml.stream.events.Attribute;
25 import javax.xml.stream.events.Characters;
26 import javax.xml.stream.events.Comment;
27 import javax.xml.stream.events.DTD;
28 import javax.xml.stream.events.EndElement;
29 import javax.xml.stream.events.EntityDeclaration;
30 import javax.xml.stream.events.EntityReference;
31 import javax.xml.stream.events.Namespace;
32 import javax.xml.stream.events.NotationDeclaration;
33 import javax.xml.stream.events.ProcessingInstruction;
34 import javax.xml.stream.events.StartElement;
35 import javax.xml.stream.events.XMLEvent;
36
37 import org.xml.sax.Attributes;
38 import org.xml.sax.SAXException;
39 import org.xml.sax.helpers.AttributesImpl;
40
41 import org.springframework.util.StringUtils;
42 import org.springframework.xml.namespace.QNameUtils;
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class StaxEventXmlReader extends AbstractStaxXmlReader {
57
58 private final XMLEventReader reader;
59
60
61
62
63
64
65
66
67
68 public StaxEventXmlReader(XMLEventReader reader) {
69 try {
70 XMLEvent event = reader.peek();
71 if (event == null || !(event.isStartDocument() || event.isStartElement())) {
72 throw new IllegalStateException("XMLEventReader not at start of document or element");
73 }
74 }
75 catch (XMLStreamException ex) {
76 throw new IllegalStateException("Could not read first element: " + ex.getMessage());
77 }
78
79 this.reader = reader;
80 }
81
82 protected void parseInternal() throws SAXException, XMLStreamException {
83 boolean documentStarted = false;
84 boolean documentEnded = false;
85 int elementDepth = 0;
86 while (reader.hasNext() && elementDepth >= 0) {
87 XMLEvent event = reader.nextEvent();
88 if (!event.isStartDocument() && !event.isEndDocument() && !documentStarted) {
89 handleStartDocument();
90 documentStarted = true;
91 }
92 switch (event.getEventType()) {
93 case XMLStreamConstants.START_ELEMENT:
94 elementDepth++;
95 handleStartElement(event.asStartElement());
96 break;
97 case XMLStreamConstants.END_ELEMENT:
98 elementDepth--;
99 if (elementDepth >= 0) {
100 handleEndElement(event.asEndElement());
101 }
102 break;
103 case XMLStreamConstants.PROCESSING_INSTRUCTION:
104 handleProcessingInstruction((ProcessingInstruction) event);
105 break;
106 case XMLStreamConstants.CHARACTERS:
107 case XMLStreamConstants.SPACE:
108 case XMLStreamConstants.CDATA:
109 handleCharacters(event.asCharacters());
110 break;
111 case XMLStreamConstants.START_DOCUMENT:
112 setLocator(event.getLocation());
113 handleStartDocument();
114 documentStarted = true;
115 break;
116 case XMLStreamConstants.END_DOCUMENT:
117 handleEndDocument();
118 documentEnded = true;
119 break;
120 case XMLStreamConstants.NOTATION_DECLARATION:
121 handleNotationDeclaration((NotationDeclaration) event);
122 break;
123 case XMLStreamConstants.ENTITY_DECLARATION:
124 handleEntityDeclaration((EntityDeclaration) event);
125 break;
126 case XMLStreamConstants.COMMENT:
127 handleComment((Comment) event);
128 break;
129 case XMLStreamConstants.DTD:
130 handleDtd((DTD) event);
131 break;
132 case XMLStreamConstants.ENTITY_REFERENCE:
133 handleEntityReference((EntityReference) event);
134 break;
135 }
136 }
137 if (!documentEnded) {
138 handleEndDocument();
139 }
140
141 }
142
143 private void handleStartElement(StartElement startElement) throws SAXException {
144 if (getContentHandler() != null) {
145 QName qName = startElement.getName();
146 if (hasNamespacesFeature()) {
147 for (Iterator i = startElement.getNamespaces(); i.hasNext();) {
148 Namespace namespace = (Namespace) i.next();
149 getContentHandler().startPrefixMapping(namespace.getPrefix(), namespace.getNamespaceURI());
150 }
151 getContentHandler().startElement(qName.getNamespaceURI(), qName.getLocalPart(),
152 QNameUtils.toQualifiedName(qName), getAttributes(startElement));
153 }
154 else {
155 getContentHandler()
156 .startElement("", "", QNameUtils.toQualifiedName(qName), getAttributes(startElement));
157 }
158 }
159 }
160
161 private void handleCharacters(Characters characters) throws SAXException {
162 char[] data = characters.getData().toCharArray();
163 if (getContentHandler() != null && characters.isIgnorableWhiteSpace()) {
164 getContentHandler().ignorableWhitespace(data, 0, data.length);
165 return;
166 }
167 if (characters.isCData() && getLexicalHandler() != null) {
168 getLexicalHandler().startCDATA();
169 }
170 if (getContentHandler() != null) {
171 getContentHandler().characters(data, 0, data.length);
172 }
173 if (characters.isCData() && getLexicalHandler() != null) {
174 getLexicalHandler().endCDATA();
175 }
176 }
177
178 private void handleEndDocument() throws SAXException {
179 if (getContentHandler() != null) {
180 getContentHandler().endDocument();
181 }
182 }
183
184 private void handleEndElement(EndElement endElement) throws SAXException {
185 if (getContentHandler() != null) {
186 QName qName = endElement.getName();
187 if (hasNamespacesFeature()) {
188 getContentHandler()
189 .endElement(qName.getNamespaceURI(), qName.getLocalPart(), QNameUtils.toQualifiedName(qName));
190 for (Iterator i = endElement.getNamespaces(); i.hasNext();) {
191 Namespace namespace = (Namespace) i.next();
192 getContentHandler().endPrefixMapping(namespace.getPrefix());
193 }
194 }
195 else {
196 getContentHandler().endElement("", "", QNameUtils.toQualifiedName(qName));
197 }
198
199 }
200 }
201
202 private void handleNotationDeclaration(NotationDeclaration declaration) throws SAXException {
203 if (getDTDHandler() != null) {
204 getDTDHandler().notationDecl(declaration.getName(), declaration.getPublicId(), declaration.getSystemId());
205 }
206 }
207
208 private void handleEntityDeclaration(EntityDeclaration entityDeclaration) throws SAXException {
209 if (getDTDHandler() != null) {
210 getDTDHandler().unparsedEntityDecl(entityDeclaration.getName(), entityDeclaration.getPublicId(),
211 entityDeclaration.getSystemId(), entityDeclaration.getNotationName());
212 }
213 }
214
215 private void handleProcessingInstruction(ProcessingInstruction pi) throws SAXException {
216 if (getContentHandler() != null) {
217 getContentHandler().processingInstruction(pi.getTarget(), pi.getData());
218 }
219 }
220
221 private void handleStartDocument() throws SAXException {
222 if (getContentHandler() != null) {
223 getContentHandler().startDocument();
224 }
225 }
226
227 private void handleComment(Comment comment) throws SAXException {
228 if (getLexicalHandler() != null) {
229 char[] ch = comment.getText().toCharArray();
230 getLexicalHandler().comment(ch, 0, ch.length);
231 }
232 }
233
234 private void handleDtd(DTD dtd) throws SAXException {
235 if (getLexicalHandler() != null) {
236 javax.xml.stream.Location location = dtd.getLocation();
237 getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
238 }
239 if (getLexicalHandler() != null) {
240 getLexicalHandler().endDTD();
241 }
242
243 }
244
245 private void handleEntityReference(EntityReference reference) throws SAXException {
246 if (getLexicalHandler() != null) {
247 getLexicalHandler().startEntity(reference.getName());
248 }
249 if (getLexicalHandler() != null) {
250 getLexicalHandler().endEntity(reference.getName());
251 }
252
253 }
254
255 private Attributes getAttributes(StartElement event) {
256 AttributesImpl attributes = new AttributesImpl();
257
258 for (Iterator i = event.getAttributes(); i.hasNext();) {
259 Attribute attribute = (Attribute) i.next();
260 QName qName = attribute.getName();
261 String namespace = qName.getNamespaceURI();
262 if (namespace == null || !hasNamespacesFeature()) {
263 namespace = "";
264 }
265 String type = attribute.getDTDType();
266 if (type == null) {
267 type = "CDATA";
268 }
269 attributes.addAttribute(namespace, qName.getLocalPart(), QNameUtils.toQualifiedName(qName), type,
270 attribute.getValue());
271 }
272 if (hasNamespacePrefixesFeature()) {
273 for (Iterator i = event.getNamespaces(); i.hasNext();) {
274 Namespace namespace = (Namespace) i.next();
275 String prefix = namespace.getPrefix();
276 String namespaceUri = namespace.getNamespaceURI();
277 String qName;
278 if (StringUtils.hasLength(prefix)) {
279 qName = "xmlns:" + prefix;
280 }
281 else {
282 qName = "xmlns";
283 }
284 attributes.addAttribute("", "", qName, "CDATA", namespaceUri);
285 }
286 }
287
288 return attributes;
289 }
290
291 }