001: /*
002: * Copyright 2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.xml.stream;
018:
019: import javax.xml.namespace.QName;
020: import javax.xml.stream.XMLStreamConstants;
021: import javax.xml.stream.XMLStreamException;
022: import javax.xml.stream.XMLStreamReader;
023:
024: import org.springframework.xml.namespace.QNameUtils;
025: import org.xml.sax.Attributes;
026: import org.xml.sax.SAXException;
027: import org.xml.sax.helpers.AttributesImpl;
028:
029: /**
030: * SAX <code>XMLReader</code> that reads from a StAX <code>XMLStreamReader</code>. Reads from an
031: * <code>XMLStreamReader</code>, and calls the corresponding methods on the SAX callback interfaces.
032: *
033: * @author Arjen Poutsma
034: * @see XMLStreamReader
035: * @see #setContentHandler(org.xml.sax.ContentHandler)
036: * @see #setDTDHandler(org.xml.sax.DTDHandler)
037: * @see #setEntityResolver(org.xml.sax.EntityResolver)
038: * @see #setErrorHandler(org.xml.sax.ErrorHandler)
039: * @since 1.0.0
040: */
041: public class StaxStreamXmlReader extends AbstractStaxXmlReader {
042:
043: private final XMLStreamReader reader;
044:
045: /**
046: * Constructs a new instance of the <code>StaxStreamXmlReader</code> that reads from the given
047: * <code>XMLStreamReader</code>. The supplied stream reader must be in <code>XMLStreamConstants.START_DOCUMENT</code>
048: * or <code>XMLStreamConstants.START_ELEMENT</code> state.
049: *
050: * @param reader the <code>XMLEventReader</code> to read from
051: * @throws IllegalStateException if the reader is not at the start of a document or element
052: */
053: public StaxStreamXmlReader(XMLStreamReader reader) {
054: int event = reader.getEventType();
055: if (!(event == XMLStreamConstants.START_DOCUMENT || event == XMLStreamConstants.START_ELEMENT)) {
056: throw new IllegalStateException(
057: "XMLEventReader not at start of document or element");
058: }
059: this .reader = reader;
060: }
061:
062: protected void parseInternal() throws SAXException,
063: XMLStreamException {
064: boolean documentStarted = false;
065: boolean documentEnded = false;
066: int elementDepth = 0;
067: int eventType = reader.getEventType();
068: while (true) {
069: if (eventType != XMLStreamConstants.START_DOCUMENT
070: && eventType != XMLStreamConstants.END_DOCUMENT
071: && !documentStarted) {
072: handleStartDocument();
073: documentStarted = true;
074: }
075: switch (eventType) {
076: case XMLStreamConstants.START_ELEMENT:
077: elementDepth++;
078: handleStartElement();
079: break;
080: case XMLStreamConstants.END_ELEMENT:
081: elementDepth--;
082: if (elementDepth >= 0) {
083: handleEndElement();
084: }
085: break;
086: case XMLStreamConstants.PROCESSING_INSTRUCTION:
087: handleProcessingInstruction();
088: break;
089: case XMLStreamConstants.CHARACTERS:
090: case XMLStreamConstants.SPACE:
091: case XMLStreamConstants.CDATA:
092: handleCharacters();
093: break;
094: case XMLStreamConstants.START_DOCUMENT:
095: setLocator(reader.getLocation());
096: handleStartDocument();
097: documentStarted = true;
098: break;
099: case XMLStreamConstants.END_DOCUMENT:
100: handleEndDocument();
101: documentEnded = true;
102: break;
103: }
104: if (reader.hasNext() && elementDepth >= 0) {
105: eventType = reader.next();
106: } else {
107: break;
108: }
109: }
110: if (!documentEnded) {
111: handleEndDocument();
112: }
113:
114: }
115:
116: private void handleCharacters() throws SAXException {
117: if (getContentHandler() != null) {
118: if (reader.isWhiteSpace()) {
119: getContentHandler().ignorableWhitespace(
120: reader.getTextCharacters(),
121: reader.getTextStart(), reader.getTextLength());
122: } else {
123: getContentHandler().characters(
124: reader.getTextCharacters(),
125: reader.getTextStart(), reader.getTextLength());
126: }
127: }
128: }
129:
130: private void handleEndDocument() throws SAXException {
131: if (getContentHandler() != null) {
132: getContentHandler().endDocument();
133: }
134: }
135:
136: private void handleEndElement() throws SAXException {
137: if (getContentHandler() != null) {
138: QName qName = reader.getName();
139: getContentHandler().endElement(qName.getNamespaceURI(),
140: qName.getLocalPart(),
141: QNameUtils.toQualifiedName(qName));
142: for (int i = 0; i < reader.getNamespaceCount(); i++) {
143: String prefix = reader.getNamespacePrefix(i);
144: if (prefix == null) {
145: prefix = "";
146: }
147: getContentHandler().endPrefixMapping(prefix);
148: }
149: }
150: }
151:
152: private void handleProcessingInstruction() throws SAXException {
153: if (getContentHandler() != null) {
154: getContentHandler().processingInstruction(
155: reader.getPITarget(), reader.getPIData());
156: }
157: }
158:
159: private void handleStartDocument() throws SAXException {
160: if (getContentHandler() != null) {
161: getContentHandler().startDocument();
162: }
163: }
164:
165: private void handleStartElement() throws SAXException {
166: if (getContentHandler() != null) {
167: for (int i = 0; i < reader.getNamespaceCount(); i++) {
168: String prefix = reader.getNamespacePrefix(i);
169: if (prefix == null) {
170: prefix = "";
171: }
172: getContentHandler().startPrefixMapping(prefix,
173: reader.getNamespaceURI(i));
174: }
175:
176: QName qName = reader.getName();
177: getContentHandler().startElement(qName.getNamespaceURI(),
178: qName.getLocalPart(),
179: QNameUtils.toQualifiedName(qName), getAttributes());
180: }
181: }
182:
183: private Attributes getAttributes() {
184: AttributesImpl attributes = new AttributesImpl();
185:
186: for (int i = 0; i < reader.getAttributeCount(); i++) {
187: String namespace = reader.getAttributeNamespace(i);
188: if (namespace == null) {
189: namespace = "";
190: }
191: String type = reader.getAttributeType(i);
192: if (type == null) {
193: type = "";
194: }
195: attributes.addAttribute(namespace, reader
196: .getAttributeLocalName(i), QNameUtils
197: .toQualifiedName(reader.getAttributeName(i)), type,
198: reader.getAttributeValue(i));
199: }
200:
201: return attributes;
202: }
203:
204: }
|