spring StaxStreamXMLReader 源码

  • 2022-08-08
  • 浏览 (244)

spring StaxStreamXMLReader 代码

文件路径:/spring-core/src/main/java/org/springframework/util/xml/StaxStreamXMLReader.java

/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.util.xml;

import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Locator2;
import org.xml.sax.helpers.AttributesImpl;

import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

/**
 * SAX {@code XMLReader} that reads from a StAX {@code XMLStreamReader}. Reads from an
 * {@code XMLStreamReader}, and calls the corresponding methods on the SAX callback interfaces.
 *
 * @author Arjen Poutsma
 * @since 3.0
 * @see XMLStreamReader
 * @see #setContentHandler(org.xml.sax.ContentHandler)
 * @see #setDTDHandler(org.xml.sax.DTDHandler)
 * @see #setEntityResolver(org.xml.sax.EntityResolver)
 * @see #setErrorHandler(org.xml.sax.ErrorHandler)
 */
class StaxStreamXMLReader extends AbstractStaxXMLReader {

	private static final String DEFAULT_XML_VERSION = "1.0";

	private final XMLStreamReader reader;

	private String xmlVersion = DEFAULT_XML_VERSION;

	@Nullable
	private String encoding;


	/**
	 * Construct a new instance of the {@code StaxStreamXmlReader} that reads from the given
	 * {@code XMLStreamReader}. The supplied stream reader must be in {@code XMLStreamConstants.START_DOCUMENT}
	 * or {@code XMLStreamConstants.START_ELEMENT} state.
	 * @param reader the {@code XMLEventReader} to read from
	 * @throws IllegalStateException if the reader is not at the start of a document or element
	 */
	StaxStreamXMLReader(XMLStreamReader reader) {
		int event = reader.getEventType();
		if (!(event == XMLStreamConstants.START_DOCUMENT || event == XMLStreamConstants.START_ELEMENT)) {
			throw new IllegalStateException("XMLEventReader not at start of document or element");
		}
		this.reader = reader;
	}


	@Override
	protected void parseInternal() throws SAXException, XMLStreamException {
		boolean documentStarted = false;
		boolean documentEnded = false;
		int elementDepth = 0;
		int eventType = this.reader.getEventType();
		while (true) {
			if (eventType != XMLStreamConstants.START_DOCUMENT && eventType != XMLStreamConstants.END_DOCUMENT &&
					!documentStarted) {
				handleStartDocument();
				documentStarted = true;
			}
			switch (eventType) {
				case XMLStreamConstants.START_ELEMENT:
					elementDepth++;
					handleStartElement();
					break;
				case XMLStreamConstants.END_ELEMENT:
					elementDepth--;
					if (elementDepth >= 0) {
						handleEndElement();
					}
					break;
				case XMLStreamConstants.PROCESSING_INSTRUCTION:
					handleProcessingInstruction();
					break;
				case XMLStreamConstants.CHARACTERS:
				case XMLStreamConstants.SPACE:
				case XMLStreamConstants.CDATA:
					handleCharacters();
					break;
				case XMLStreamConstants.START_DOCUMENT:
					handleStartDocument();
					documentStarted = true;
					break;
				case XMLStreamConstants.END_DOCUMENT:
					handleEndDocument();
					documentEnded = true;
					break;
				case XMLStreamConstants.COMMENT:
					handleComment();
					break;
				case XMLStreamConstants.DTD:
					handleDtd();
					break;
				case XMLStreamConstants.ENTITY_REFERENCE:
					handleEntityReference();
					break;
			}
			if (this.reader.hasNext() && elementDepth >= 0) {
				eventType = this.reader.next();
			}
			else {
				break;
			}
		}
		if (!documentEnded) {
			handleEndDocument();
		}
	}

	private void handleStartDocument() throws SAXException {
		if (XMLStreamConstants.START_DOCUMENT == this.reader.getEventType()) {
			String xmlVersion = this.reader.getVersion();
			if (StringUtils.hasLength(xmlVersion)) {
				this.xmlVersion = xmlVersion;
			}
			this.encoding = this.reader.getCharacterEncodingScheme();
		}

		ContentHandler contentHandler = getContentHandler();
		if (contentHandler != null) {
			final Location location = this.reader.getLocation();
			contentHandler.setDocumentLocator(new Locator2() {
				@Override
				public int getColumnNumber() {
					return (location != null ? location.getColumnNumber() : -1);
				}
				@Override
				public int getLineNumber() {
					return (location != null ? location.getLineNumber() : -1);
				}
				@Override
				@Nullable
				public String getPublicId() {
					return (location != null ? location.getPublicId() : null);
				}
				@Override
				@Nullable
				public String getSystemId() {
					return (location != null ? location.getSystemId() : null);
				}
				@Override
				public String getXMLVersion() {
					return xmlVersion;
				}
				@Override
				@Nullable
				public String getEncoding() {
					return encoding;
				}
			});
			contentHandler.startDocument();
			if (this.reader.standaloneSet()) {
				setStandalone(this.reader.isStandalone());
			}
		}
	}

	private void handleStartElement() throws SAXException {
		if (getContentHandler() != null) {
			QName qName = this.reader.getName();
			if (hasNamespacesFeature()) {
				for (int i = 0; i < this.reader.getNamespaceCount(); i++) {
					startPrefixMapping(this.reader.getNamespacePrefix(i), this.reader.getNamespaceURI(i));
				}
				for (int i = 0; i < this.reader.getAttributeCount(); i++) {
					String prefix = this.reader.getAttributePrefix(i);
					String namespace = this.reader.getAttributeNamespace(i);
					if (StringUtils.hasLength(namespace)) {
						startPrefixMapping(prefix, namespace);
					}
				}
				getContentHandler().startElement(qName.getNamespaceURI(), qName.getLocalPart(),
						toQualifiedName(qName), getAttributes());
			}
			else {
				getContentHandler().startElement("", "", toQualifiedName(qName), getAttributes());
			}
		}
	}

	private void handleEndElement() throws SAXException {
		if (getContentHandler() != null) {
			QName qName = this.reader.getName();
			if (hasNamespacesFeature()) {
				getContentHandler().endElement(qName.getNamespaceURI(), qName.getLocalPart(), toQualifiedName(qName));
				for (int i = 0; i < this.reader.getNamespaceCount(); i++) {
					String prefix = this.reader.getNamespacePrefix(i);
					if (prefix == null) {
						prefix = "";
					}
					endPrefixMapping(prefix);
				}
			}
			else {
				getContentHandler().endElement("", "", toQualifiedName(qName));
			}
		}
	}

	private void handleCharacters() throws SAXException {
		if (XMLStreamConstants.CDATA == this.reader.getEventType() && getLexicalHandler() != null) {
			getLexicalHandler().startCDATA();
		}
		if (getContentHandler() != null) {
			getContentHandler().characters(this.reader.getTextCharacters(),
					this.reader.getTextStart(), this.reader.getTextLength());
		}
		if (XMLStreamConstants.CDATA == this.reader.getEventType() && getLexicalHandler() != null) {
			getLexicalHandler().endCDATA();
		}
	}

	private void handleComment() throws SAXException {
		if (getLexicalHandler() != null) {
			getLexicalHandler().comment(this.reader.getTextCharacters(),
					this.reader.getTextStart(), this.reader.getTextLength());
		}
	}

	private void handleDtd() throws SAXException {
		if (getLexicalHandler() != null) {
			Location location = this.reader.getLocation();
			getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
		}
		if (getLexicalHandler() != null) {
			getLexicalHandler().endDTD();
		}
	}

	private void handleEntityReference() throws SAXException {
		if (getLexicalHandler() != null) {
			getLexicalHandler().startEntity(this.reader.getLocalName());
		}
		if (getLexicalHandler() != null) {
			getLexicalHandler().endEntity(this.reader.getLocalName());
		}
	}

	private void handleEndDocument() throws SAXException {
		if (getContentHandler() != null) {
			getContentHandler().endDocument();
		}
	}

	private void handleProcessingInstruction() throws SAXException {
		if (getContentHandler() != null) {
			getContentHandler().processingInstruction(this.reader.getPITarget(), this.reader.getPIData());
		}
	}

	private Attributes getAttributes() {
		AttributesImpl attributes = new AttributesImpl();
		for (int i = 0; i < this.reader.getAttributeCount(); i++) {
			String namespace = this.reader.getAttributeNamespace(i);
			if (namespace == null || !hasNamespacesFeature()) {
				namespace = "";
			}
			String type = this.reader.getAttributeType(i);
			if (type == null) {
				type = "CDATA";
			}
			attributes.addAttribute(namespace, this.reader.getAttributeLocalName(i),
					toQualifiedName(this.reader.getAttributeName(i)), type, this.reader.getAttributeValue(i));
		}
		if (hasNamespacePrefixesFeature()) {
			for (int i = 0; i < this.reader.getNamespaceCount(); i++) {
				String prefix = this.reader.getNamespacePrefix(i);
				String namespaceUri = this.reader.getNamespaceURI(i);
				String qName;
				if (StringUtils.hasLength(prefix)) {
					qName = "xmlns:" + prefix;
				}
				else {
					qName = "xmlns";
				}
				attributes.addAttribute("", "", qName, "CDATA", namespaceUri);
			}
		}

		return attributes;
	}

}

相关信息

spring 源码目录

相关文章

spring AbstractStaxHandler 源码

spring AbstractStaxXMLReader 源码

spring AbstractXMLEventReader 源码

spring AbstractXMLReader 源码

spring AbstractXMLStreamReader 源码

spring DomContentHandler 源码

spring DomUtils 源码

spring ListBasedXMLEventReader 源码

spring SimpleNamespaceContext 源码

spring SimpleSaxErrorHandler 源码

0  赞