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 javax.xml.namespace.QName;
20 import javax.xml.stream.XMLStreamConstants;
21 import javax.xml.stream.XMLStreamException;
22 import javax.xml.stream.XMLStreamReader;
23
24 import org.xml.sax.Attributes;
25 import org.xml.sax.SAXException;
26 import org.xml.sax.helpers.AttributesImpl;
27
28 import org.springframework.util.StringUtils;
29 import org.springframework.xml.namespace.QNameUtils;
30 import org.springframework.xml.namespace.SimpleNamespaceContext;
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class StaxStreamXmlReader extends AbstractStaxXmlReader {
45
46 private final XMLStreamReader reader;
47
48 private final SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
49
50
51
52
53
54
55
56
57
58 public StaxStreamXmlReader(XMLStreamReader reader) {
59 int event = reader.getEventType();
60 if (!(event == XMLStreamConstants.START_DOCUMENT || event == XMLStreamConstants.START_ELEMENT)) {
61 throw new IllegalStateException("XMLEventReader not at start of document or element");
62 }
63 this.reader = reader;
64 }
65
66 protected void parseInternal() throws SAXException, XMLStreamException {
67 boolean documentStarted = false;
68 boolean documentEnded = false;
69 int elementDepth = 0;
70 int eventType = reader.getEventType();
71 while (true) {
72 if (eventType != XMLStreamConstants.START_DOCUMENT && eventType != XMLStreamConstants.END_DOCUMENT &&
73 !documentStarted) {
74 handleStartDocument();
75 documentStarted = true;
76 }
77 switch (eventType) {
78 case XMLStreamConstants.START_ELEMENT:
79 elementDepth++;
80 handleStartElement();
81 break;
82 case XMLStreamConstants.END_ELEMENT:
83 elementDepth--;
84 if (elementDepth >= 0) {
85 handleEndElement();
86 }
87 break;
88 case XMLStreamConstants.PROCESSING_INSTRUCTION:
89 handleProcessingInstruction();
90 break;
91 case XMLStreamConstants.CHARACTERS:
92 case XMLStreamConstants.SPACE:
93 case XMLStreamConstants.CDATA:
94 handleCharacters();
95 break;
96 case XMLStreamConstants.START_DOCUMENT:
97 setLocator(reader.getLocation());
98 handleStartDocument();
99 documentStarted = true;
100 break;
101 case XMLStreamConstants.END_DOCUMENT:
102 handleEndDocument();
103 documentEnded = true;
104 break;
105 case XMLStreamConstants.COMMENT:
106 handleComment();
107 break;
108 case XMLStreamConstants.DTD:
109 handleDtd();
110 break;
111 case XMLStreamConstants.ENTITY_REFERENCE:
112 handleEntityReference();
113 break;
114 }
115 if (reader.hasNext() && elementDepth >= 0) {
116 eventType = reader.next();
117 }
118 else {
119 break;
120 }
121 }
122 if (!documentEnded) {
123 handleEndDocument();
124 }
125 }
126
127 private void handleStartDocument() throws SAXException {
128 if (getContentHandler() != null) {
129 getContentHandler().startDocument();
130 if (reader.standaloneSet()) {
131 setStandalone(reader.isStandalone());
132 }
133 }
134 }
135
136 private void handleStartElement() throws SAXException {
137 if (getContentHandler() != null) {
138 QName qName = reader.getName();
139 if (hasNamespacesFeature()) {
140 for (int i = 0; i < reader.getNamespaceCount(); i++) {
141 String prefix = reader.getNamespacePrefix(i);
142 if (prefix == null) {
143 prefix = "";
144 }
145 startPrefixMapping(prefix, reader.getNamespaceURI(i));
146 }
147 for (int i = 0; i < reader.getAttributeCount(); i++) {
148 String prefix = reader.getAttributePrefix(i);
149 if (prefix == null) {
150 prefix = "";
151 }
152 String namespace = reader.getAttributeNamespace(i);
153 if (namespace == null) {
154 continue;
155 }
156 startPrefixMapping(prefix, namespace);
157 }
158 getContentHandler()
159 .startElement(qName.getNamespaceURI(), qName.getLocalPart(), QNameUtils.toQualifiedName(qName),
160 getAttributes());
161 }
162 else {
163 getContentHandler().startElement("", "", QNameUtils.toQualifiedName(qName), getAttributes());
164 }
165 }
166 }
167
168 private void startPrefixMapping(String prefix, String namespace) throws SAXException {
169 if (!namespaceContext.getNamespaceURI(prefix).equals(namespace)) {
170 getContentHandler().startPrefixMapping(prefix, namespace);
171 namespaceContext.bindNamespaceUri(prefix, namespace);
172 }
173 }
174
175 private void handleEndElement() throws SAXException {
176 if (getContentHandler() != null) {
177 QName qName = reader.getName();
178 if (hasNamespacesFeature()) {
179 getContentHandler()
180 .endElement(qName.getNamespaceURI(), qName.getLocalPart(), QNameUtils.toQualifiedName(qName));
181 for (int i = 0; i < reader.getNamespaceCount(); i++) {
182 String prefix = reader.getNamespacePrefix(i);
183 if (prefix == null) {
184 prefix = "";
185 }
186 endPrefixMapping(prefix);
187 }
188 }
189 else {
190 getContentHandler().endElement("", "", QNameUtils.toQualifiedName(qName));
191 }
192 }
193 }
194
195 private void endPrefixMapping(String prefix) throws SAXException {
196 if (namespaceContext.hasBinding(prefix)) {
197 getContentHandler().endPrefixMapping(prefix);
198 namespaceContext.removeBinding(prefix);
199 }
200 }
201
202 private void handleCharacters() throws SAXException {
203 if (getContentHandler() != null && reader.isWhiteSpace()) {
204 getContentHandler()
205 .ignorableWhitespace(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
206 return;
207 }
208 if (XMLStreamConstants.CDATA == reader.getEventType() && getLexicalHandler() != null) {
209 getLexicalHandler().startCDATA();
210 }
211 if (getContentHandler() != null) {
212 getContentHandler().characters(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
213 }
214 if (XMLStreamConstants.CDATA == reader.getEventType() && getLexicalHandler() != null) {
215 getLexicalHandler().endCDATA();
216 }
217 }
218
219 private void handleComment() throws SAXException {
220 if (getLexicalHandler() != null) {
221 getLexicalHandler().comment(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
222 }
223 }
224
225 private void handleDtd() throws SAXException {
226 if (getLexicalHandler() != null) {
227 javax.xml.stream.Location location = reader.getLocation();
228 getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
229 }
230 if (getLexicalHandler() != null) {
231 getLexicalHandler().endDTD();
232 }
233 }
234
235 private void handleEntityReference() throws SAXException {
236 if (getLexicalHandler() != null) {
237 getLexicalHandler().startEntity(reader.getLocalName());
238 }
239 if (getLexicalHandler() != null) {
240 getLexicalHandler().endEntity(reader.getLocalName());
241 }
242 }
243
244 private void handleEndDocument() throws SAXException {
245 if (getContentHandler() != null) {
246 getContentHandler().endDocument();
247 }
248 }
249
250 private void handleProcessingInstruction() throws SAXException {
251 if (getContentHandler() != null) {
252 getContentHandler().processingInstruction(reader.getPITarget(), reader.getPIData());
253 }
254 }
255
256 private Attributes getAttributes() {
257 AttributesImpl attributes = new AttributesImpl();
258
259 for (int i = 0; i < reader.getAttributeCount(); i++) {
260 String namespace = reader.getAttributeNamespace(i);
261 if (namespace == null || !hasNamespacesFeature()) {
262 namespace = "";
263 }
264 String type = reader.getAttributeType(i);
265 if (type == null) {
266 type = "CDATA";
267 }
268 attributes.addAttribute(namespace, reader.getAttributeLocalName(i),
269 QNameUtils.toQualifiedName(reader.getAttributeName(i)), type, reader.getAttributeValue(i));
270 }
271 if (hasNamespacePrefixesFeature()) {
272 for (int i = 0; i < reader.getNamespaceCount(); i++) {
273 String prefix = reader.getNamespacePrefix(i);
274 String namespaceUri = reader.getNamespaceURI(i);
275 String qName;
276 if (StringUtils.hasLength(prefix)) {
277 qName = "xmlns:" + prefix;
278 }
279 else {
280 qName = "xmlns";
281 }
282 attributes.addAttribute("", "", qName, "CDATA", namespaceUri);
283 }
284 }
285
286 return attributes;
287 }
288
289 }