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 java.util.Iterator;
020: import javax.xml.stream.XMLEventReader;
021: import javax.xml.stream.XMLStreamConstants;
022: import javax.xml.stream.XMLStreamException;
023: import javax.xml.stream.events.Attribute;
024: import javax.xml.stream.events.Characters;
025: import javax.xml.stream.events.EndElement;
026: import javax.xml.stream.events.EntityDeclaration;
027: import javax.xml.stream.events.Namespace;
028: import javax.xml.stream.events.NotationDeclaration;
029: import javax.xml.stream.events.ProcessingInstruction;
030: import javax.xml.stream.events.StartElement;
031: import javax.xml.stream.events.XMLEvent;
032:
033: import org.springframework.xml.namespace.QNameUtils;
034: import org.xml.sax.Attributes;
035: import org.xml.sax.SAXException;
036: import org.xml.sax.helpers.AttributesImpl;
037:
038: /**
039: * SAX <code>XMLReader</code> that reads from a StAX <code>XMLEventReader</code>. Consumes <code>XMLEvents</code> from
040: * an <code>XMLEventReader</code>, and calls the corresponding methods on the SAX callback interfaces.
041: *
042: * @author Arjen Poutsma
043: * @see XMLEventReader
044: * @see #setContentHandler(org.xml.sax.ContentHandler)
045: * @see #setDTDHandler(org.xml.sax.DTDHandler)
046: * @see #setEntityResolver(org.xml.sax.EntityResolver)
047: * @see #setErrorHandler(org.xml.sax.ErrorHandler)
048: * @since 1.0.0
049: */
050: public class StaxEventXmlReader extends AbstractStaxXmlReader {
051:
052: private final XMLEventReader reader;
053:
054: /**
055: * Constructs a new instance of the <code>StaxEventXmlReader</code> that reads from the given
056: * <code>XMLEventReader</code>. The supplied event reader must be in <code>XMLStreamConstants.START_DOCUMENT</code>
057: * or <code>XMLStreamConstants.START_ELEMENT</code> state.
058: *
059: * @param reader the <code>XMLEventReader</code> to read from
060: * @throws IllegalStateException if the reader is not at the start of a document or element
061: */
062: public StaxEventXmlReader(XMLEventReader reader) {
063: try {
064: XMLEvent event = reader.peek();
065: if (event == null
066: || !(event.isStartDocument() || event
067: .isStartElement())) {
068: throw new IllegalStateException(
069: "XMLEventReader not at start of document or element");
070: }
071: } catch (XMLStreamException ex) {
072: throw new IllegalStateException(
073: "Could not read first element: " + ex.getMessage());
074: }
075:
076: this .reader = reader;
077: }
078:
079: protected void parseInternal() throws SAXException,
080: XMLStreamException {
081: boolean documentStarted = false;
082: boolean documentEnded = false;
083: int elementDepth = 0;
084: XMLEvent event = null;
085: while (reader.hasNext() && elementDepth >= 0) {
086: event = reader.nextEvent();
087: if (!event.isStartDocument() && !event.isEndDocument()
088: && !documentStarted) {
089: handleStartDocument();
090: documentStarted = true;
091: }
092: switch (event.getEventType()) {
093: case XMLStreamConstants.START_ELEMENT:
094: elementDepth++;
095: handleStartElement(event.asStartElement());
096: break;
097: case XMLStreamConstants.END_ELEMENT:
098: elementDepth--;
099: 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: }
127: }
128: if (!documentEnded) {
129: handleEndDocument();
130: }
131:
132: }
133:
134: private void handleCharacters(Characters characters)
135: throws SAXException {
136: if (getContentHandler() != null) {
137: if (characters.isIgnorableWhiteSpace()) {
138: getContentHandler().ignorableWhitespace(
139: characters.getData().toCharArray(), 0,
140: characters.getData().length());
141: } else {
142: getContentHandler().characters(
143: characters.getData().toCharArray(), 0,
144: characters.getData().length());
145: }
146: }
147: }
148:
149: private void handleEndDocument() throws SAXException {
150: if (getContentHandler() != null) {
151: getContentHandler().endDocument();
152: }
153: }
154:
155: private void handleEndElement(EndElement endElement)
156: throws SAXException {
157: if (getContentHandler() != null) {
158: getContentHandler().endElement(
159: endElement.getName().getNamespaceURI(),
160: endElement.getName().getLocalPart(),
161: QNameUtils.toQualifiedName(endElement.getName()));
162:
163: for (Iterator i = endElement.getNamespaces(); i.hasNext();) {
164: Namespace namespace = (Namespace) i.next();
165: getContentHandler().endPrefixMapping(
166: namespace.getPrefix());
167: }
168: }
169: }
170:
171: private void handleNotationDeclaration(
172: NotationDeclaration declaration) throws SAXException {
173: if (getDTDHandler() != null) {
174: getDTDHandler().notationDecl(declaration.getName(),
175: declaration.getPublicId(),
176: declaration.getSystemId());
177: }
178: }
179:
180: private void handleEntityDeclaration(
181: EntityDeclaration entityDeclaration) throws SAXException {
182: if (getDTDHandler() != null) {
183: getDTDHandler().unparsedEntityDecl(
184: entityDeclaration.getName(),
185: entityDeclaration.getPublicId(),
186: entityDeclaration.getSystemId(),
187: entityDeclaration.getNotationName());
188: }
189: }
190:
191: private void handleProcessingInstruction(ProcessingInstruction pi)
192: throws SAXException {
193: if (getContentHandler() != null) {
194: getContentHandler().processingInstruction(pi.getTarget(),
195: pi.getData());
196: }
197: }
198:
199: private void handleStartDocument() throws SAXException {
200: if (getContentHandler() != null) {
201: getContentHandler().startDocument();
202: }
203: }
204:
205: private void handleStartElement(StartElement startElement)
206: throws SAXException {
207: if (getContentHandler() != null) {
208: for (Iterator i = startElement.getNamespaces(); i.hasNext();) {
209: Namespace namespace = (Namespace) i.next();
210: getContentHandler().startPrefixMapping(
211: namespace.getPrefix(),
212: namespace.getNamespaceURI());
213: }
214:
215: getContentHandler().startElement(
216: startElement.getName().getNamespaceURI(),
217: startElement.getName().getLocalPart(),
218: QNameUtils.toQualifiedName(startElement.getName()),
219: getAttributes(startElement));
220: }
221: }
222:
223: private Attributes getAttributes(StartElement event) {
224: AttributesImpl attributes = new AttributesImpl();
225:
226: for (Iterator i = event.getAttributes(); i.hasNext();) {
227: Attribute attribute = (Attribute) i.next();
228: attributes.addAttribute(attribute.getName()
229: .getNamespaceURI(), attribute.getName()
230: .getLocalPart(), QNameUtils
231: .toQualifiedName(attribute.getName()), attribute
232: .getDTDType(), attribute.getValue());
233: }
234:
235: return attributes;
236: }
237:
238: }
|