View Javadoc

1   /*
2    * Copyright 2006 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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.springframework.xml.namespace.QNameUtils;
25  import org.xml.sax.Attributes;
26  import org.xml.sax.SAXException;
27  import org.xml.sax.helpers.AttributesImpl;
28  
29  /**
30   * SAX <code>XMLReader</code> that reads from a StAX <code>XMLStreamReader</code>.  Reads from an
31   * <code>XMLStreamReader</code>, and calls the corresponding methods on the SAX callback interfaces.
32   *
33   * @author Arjen Poutsma
34   * @see XMLStreamReader
35   * @see #setContentHandler(org.xml.sax.ContentHandler)
36   * @see #setDTDHandler(org.xml.sax.DTDHandler)
37   * @see #setEntityResolver(org.xml.sax.EntityResolver)
38   * @see #setErrorHandler(org.xml.sax.ErrorHandler)
39   * @since 1.0.0
40   */
41  public class StaxStreamXmlReader extends AbstractStaxXmlReader {
42  
43      private final XMLStreamReader reader;
44  
45      /**
46       * Constructs a new instance of the <code>StaxStreamXmlReader</code> that reads from the given
47       * <code>XMLStreamReader</code>.  The supplied stream reader must be in <code>XMLStreamConstants.START_DOCUMENT</code>
48       * or <code>XMLStreamConstants.START_ELEMENT</code> state.
49       *
50       * @param reader the <code>XMLEventReader</code> to read from
51       * @throws IllegalStateException if the reader is not at the start of a document or element
52       */
53      public StaxStreamXmlReader(XMLStreamReader reader) {
54          int event = reader.getEventType();
55          if (!(event == XMLStreamConstants.START_DOCUMENT || event == XMLStreamConstants.START_ELEMENT)) {
56              throw new IllegalStateException("XMLEventReader not at start of document or element");
57          }
58          this.reader = reader;
59      }
60  
61      protected void parseInternal() throws SAXException, XMLStreamException {
62          boolean documentStarted = false;
63          boolean documentEnded = false;
64          int elementDepth = 0;
65          int eventType = reader.getEventType();
66          while (true) {
67              if (eventType != XMLStreamConstants.START_DOCUMENT && eventType != XMLStreamConstants.END_DOCUMENT &&
68                      !documentStarted) {
69                  handleStartDocument();
70                  documentStarted = true;
71              }
72              switch (eventType) {
73                  case XMLStreamConstants.START_ELEMENT:
74                      elementDepth++;
75                      handleStartElement();
76                      break;
77                  case XMLStreamConstants.END_ELEMENT:
78                      elementDepth--;
79                      if (elementDepth >= 0) {
80                          handleEndElement();
81                      }
82                      break;
83                  case XMLStreamConstants.PROCESSING_INSTRUCTION:
84                      handleProcessingInstruction();
85                      break;
86                  case XMLStreamConstants.CHARACTERS:
87                  case XMLStreamConstants.SPACE:
88                  case XMLStreamConstants.CDATA:
89                      handleCharacters();
90                      break;
91                  case XMLStreamConstants.START_DOCUMENT:
92                      setLocator(reader.getLocation());
93                      handleStartDocument();
94                      documentStarted = true;
95                      break;
96                  case XMLStreamConstants.END_DOCUMENT:
97                      handleEndDocument();
98                      documentEnded = true;
99                      break;
100             }
101             if (reader.hasNext() && elementDepth >= 0) {
102                 eventType = reader.next();
103             }
104             else {
105                 break;
106             }
107         }
108         if (!documentEnded) {
109             handleEndDocument();
110         }
111 
112     }
113 
114     private void handleCharacters() throws SAXException {
115         if (getContentHandler() != null) {
116             if (reader.isWhiteSpace()) {
117                 getContentHandler()
118                         .ignorableWhitespace(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
119             }
120             else {
121                 getContentHandler()
122                         .characters(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
123             }
124         }
125     }
126 
127     private void handleEndDocument() throws SAXException {
128         if (getContentHandler() != null) {
129             getContentHandler().endDocument();
130         }
131     }
132 
133     private void handleEndElement() throws SAXException {
134         if (getContentHandler() != null) {
135             QName qName = reader.getName();
136             getContentHandler()
137                     .endElement(qName.getNamespaceURI(), qName.getLocalPart(), QNameUtils.toQualifiedName(qName));
138             for (int i = 0; i < reader.getNamespaceCount(); i++) {
139                 String prefix = reader.getNamespacePrefix(i);
140                 if (prefix == null) {
141                     prefix = "";
142                 }
143                 getContentHandler().endPrefixMapping(prefix);
144             }
145         }
146     }
147 
148     private void handleProcessingInstruction() throws SAXException {
149         if (getContentHandler() != null) {
150             getContentHandler().processingInstruction(reader.getPITarget(), reader.getPIData());
151         }
152     }
153 
154     private void handleStartDocument() throws SAXException {
155         if (getContentHandler() != null) {
156             getContentHandler().startDocument();
157         }
158     }
159 
160     private void handleStartElement() throws SAXException {
161         if (getContentHandler() != null) {
162             for (int i = 0; i < reader.getNamespaceCount(); i++) {
163                 String prefix = reader.getNamespacePrefix(i);
164                 if (prefix == null) {
165                     prefix = "";
166                 }
167                 getContentHandler().startPrefixMapping(prefix, reader.getNamespaceURI(i));
168             }
169 
170             QName qName = reader.getName();
171             getContentHandler().startElement(qName.getNamespaceURI(), qName.getLocalPart(),
172                     QNameUtils.toQualifiedName(qName), getAttributes());
173         }
174     }
175 
176     private Attributes getAttributes() {
177         AttributesImpl attributes = new AttributesImpl();
178 
179         for (int i = 0; i < reader.getAttributeCount(); i++) {
180             String namespace = reader.getAttributeNamespace(i);
181             if (namespace == null) {
182                 namespace = "";
183             }
184             String type = reader.getAttributeType(i);
185             if (type == null) {
186                 type = "";
187             }
188             attributes.addAttribute(namespace, reader.getAttributeLocalName(i),
189                     QNameUtils.toQualifiedName(reader.getAttributeName(i)), type, reader.getAttributeValue(i));
190         }
191 
192         return attributes;
193     }
194 
195 
196 }