All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.xml.serializer.ToXMLStream Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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
 *
 *     http://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.
 */
/*
 * $Id: ToXMLStream.java 469359 2006-10-31 03:43:19Z minchau $
 */

package org.apache.xml.serializer;

import java.io.IOException;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;

import org.apache.xml.serializer.utils.MsgKey;
import org.apache.xml.serializer.utils.Utils;
import org.xml.sax.SAXException;

import com.sta.mlogger.MLogger;

/**
 * 

Name: ToXMLStream

*

Description: Klasse wg. Zeilenumbruch-Bug ersetzt. *

*

Comment: ... * This class converts SAX or SAX-like calls to a serialized xml document. The xsl:output method is "xml". * This class is used explicitly in code generated by XSLTC, so it is "public", but it should * be viewed as internal or package private, this is not an API. * _xsl.usage internal *

*

Copyright: Copyright (c) 2019, 2021

*

Company: >StA-Soft<

* @author StA * @version 1.0 */ public class ToXMLStream extends ToStream { /** * Map that tells which XML characters should have special treatment, and it * provides character to entity name lookup. */ private CharInfo m_xmlcharInfo = CharInfo.getCharInfo(CharInfo.XML_ENTITIES_RESOURCE, Method.XML); /** * Default constructor. */ public ToXMLStream() { m_charInfo = m_xmlcharInfo; initCDATA(); // initialize namespaces m_prefixMap = new NamespaceMappings(); } /** * Copy properties from another SerializerToXML. * @param xmlListener non-null reference to a SerializerToXML object. */ public void copyFrom(ToXMLStream xmlListener) { setWriter(xmlListener.m_writer); // m_outputStream = xmlListener.m_outputStream; String encoding = xmlListener.getEncoding(); setEncoding(encoding); setOmitXMLDeclaration(xmlListener.getOmitXMLDeclaration()); m_ispreserve = xmlListener.m_ispreserve; m_preserves = xmlListener.m_preserves; m_isprevtext = xmlListener.m_isprevtext; m_doIndent = xmlListener.m_doIndent; setIndentAmount(xmlListener.getIndentAmount()); m_startNewLine = xmlListener.m_startNewLine; m_needToOutputDocTypeDecl = xmlListener.m_needToOutputDocTypeDecl; setDoctypeSystem(xmlListener.getDoctypeSystem()); setDoctypePublic(xmlListener.getDoctypePublic()); setStandalone(xmlListener.getStandalone()); setMediaType(xmlListener.getMediaType()); m_encodingInfo = xmlListener.m_encodingInfo; m_spaceBeforeClose = xmlListener.m_spaceBeforeClose; m_cdataStartCalled = xmlListener.m_cdataStartCalled; } @Override public void startDocumentInternal() throws org.xml.sax.SAXException { if (m_needToCallStartDocument) { super.startDocumentInternal(); m_needToCallStartDocument = false; if (m_inEntityRef) { return; } m_needToOutputDocTypeDecl = true; m_startNewLine = false; /* The call to getXMLVersion() might emit an error message * and we should emit this message regardless of if we are * writing out an XML header or not. */ final String version = getXMLVersion(); if (!getOmitXMLDeclaration()) { String encoding = Encodings.getMimeEncoding(getEncoding()); String standalone; if (m_standaloneWasSpecified) { standalone = " standalone=\"" + getStandalone() + "\""; } else { standalone = ""; } try { final java.io.Writer writer = m_writer; writer.write(""); if (m_doIndent) { // if (m_standaloneWasSpecified || (getDoctypePublic() != null) || (getDoctypeSystem() != null) || true) // { // We almost never put a newline after the XML // header because this XML could be used as // an extenal general parsed entity // and we don't know the context into which it // will be used in the future. Only when // standalone, or a doctype system or public is // specified are we free to insert a new line // after the header. Is it even worth bothering // in these rare cases? writer.write(m_lineSep, 0, m_lineSepLen); // } } } catch (IOException e) { throw new SAXException(e); } } } } @Override public void endDocument() throws org.xml.sax.SAXException { flushPending(); if (m_doIndent && !m_isprevtext) { try { outputLineSep(); } catch (IOException e) { throw new SAXException(e); } } flushWriter(); if (m_tracer != null) { super.fireEndDoc(); } } /** * Starts a whitespace preserving section. All characters printed * within a preserving section are printed without indentation and * without consolidating multiple spaces. This is equivalent to * the xml:space="preserve" attribute. Only XML * and HTML serializers need to support this method. *

* The contents of the whitespace preserving section will be delivered * through the regular characters event. * @throws org.xml.sax.SAXException in case of an error */ public void startPreserving() throws org.xml.sax.SAXException { // Not sure this is really what we want. -sb m_preserves.push(true); m_ispreserve = true; } /** * Ends a whitespace preserving section. * @throws org.xml.sax.SAXException in case of an error * @see #startPreserving */ public void endPreserving() throws org.xml.sax.SAXException { // Not sure this is really what we want. -sb m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop(); } @Override public void processingInstruction(String target, String data) throws org.xml.sax.SAXException { if (m_inEntityRef) { return; } flushPending(); if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING)) { startNonEscaping(); } else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING)) { endNonEscaping(); } else { try { if (m_elemContext.m_startTagOpen) { closeStartTag(); m_elemContext.m_startTagOpen = false; } else if (m_needToCallStartDocument) { startDocumentInternal(); } if (shouldIndent()) { indent(); } final java.io.Writer writer = m_writer; writer.write(" 0) && !Character.isSpaceChar(data.charAt(0))) { writer.write(' '); } int indexOfQLT = data.indexOf("?>"); if (indexOfQLT >= 0) { // See XSLT spec on error recovery of "?>" in PIs. if (indexOfQLT > 0) { writer.write(data.substring(0, indexOfQLT)); } writer.write("? >"); // add space between. if ((indexOfQLT + 2) < data.length()) { writer.write(data.substring(indexOfQLT + 2)); } } else { writer.write(data); } writer.write('?'); writer.write('>'); /* * Don't write out any indentation whitespace now, * because there may be non-whitespace text after this. * * Simply mark that at this point if we do decide * to indent that we should * add a newline on the end of the current line before * the indentation at the start of the next line. */ m_startNewLine = true; } catch (IOException e) { throw new SAXException(e); } } if (m_tracer != null) { super.fireEscapingEvent(target, data); } } @Override public void entityReference(String name) throws org.xml.sax.SAXException { if (m_elemContext.m_startTagOpen) { closeStartTag(); m_elemContext.m_startTagOpen = false; } try { if (shouldIndent()) { indent(); } final java.io.Writer writer = m_writer; writer.write('&'); writer.write(name); writer.write(';'); } catch (IOException e) { throw new SAXException(e); } if (m_tracer != null) { super.fireEntityReference(name); } } @Override public void addUniqueAttribute(String name, String value, int flags) throws SAXException { if (m_elemContext.m_startTagOpen) { try { final String patchedName = patchName(name); final java.io.Writer writer = m_writer; if ((flags & NO_BAD_CHARS) > 0 && m_xmlcharInfo.onlyQuotAmpLtGt) { // "flags" has indicated that the characters // '>' '<' '&' and '"' are not in the value and // m_htmlcharInfo has recorded that there are no other // entities in the range 32 to 127 so we write out the // value directly writer.write(' '); writer.write(patchedName); writer.write("=\""); writer.write(value); writer.write('"'); } else { writer.write(' '); writer.write(patchedName); writer.write("=\""); writeAttrString(writer, value, this.getEncoding()); writer.write('"'); } } catch (IOException e) { throw new SAXException(e); } } } @Override public void addAttribute( String uri, String localName, String rawName, String type, String value, boolean xslAttribute) throws SAXException { if (m_elemContext.m_startTagOpen) { boolean was_added = addAttributeAlways(uri, localName, rawName, type, value, xslAttribute); /* * We don't run this block of code if: * 1. The attribute value was only replaced (was_added is false). * 2. The attribute is from an xsl:attribute element (that is handled * in the addAttributeAlways() call just above. * 3. The name starts with "xmlns", i.e. it is a namespace declaration. */ if (was_added && !xslAttribute && !rawName.startsWith("xmlns")) { String prefixUsed = ensureAttributesNamespaceIsDeclared(uri, localName, rawName); if ((prefixUsed != null) && (rawName != null) && !rawName.startsWith(prefixUsed)) { // use a different raw name, with the prefix used in the // generated namespace declaration rawName = prefixUsed + ":" + localName; } } addAttributeAlways(uri, localName, rawName, type, value, xslAttribute); } else { /* * The startTag is closed, yet we are adding an attribute? * * Section: 7.1.3 Creating Attributes Adding an attribute to an * element after a PI (for example) has been added to it is an * error. The attributes can be ignored. The spec doesn't explicitly * say this is disallowed, as it does for child elements, but it * makes sense to have the same treatment. * * We choose to ignore the attribute which is added too late. */ // Generate a warning of the ignored attributes // Create the warning message String msg = Utils.messages.createMessage( MsgKey.ER_ILLEGAL_ATTRIBUTE_POSITION, new Object[]{localName}); try { // Prepare to issue the warning message Transformer tran = super.getTransformer(); ErrorListener errHandler = tran.getErrorListener(); // Issue the warning message if (null != errHandler && m_sourceLocator != null) { errHandler.warning(new TransformerException(msg, m_sourceLocator)); } else { MLogger.inf(msg); } } catch (TransformerException e) { // A user defined error handler, errHandler, may throw // a TransformerException if it chooses to, and if it does // we will wrap it with a SAXException and re-throw. // Of course if the handler throws another type of // exception, like a RuntimeException, then that is OK too. SAXException se = new SAXException(e); throw se; } } } @Override public void endElement(String elemName) throws SAXException { endElement(null, null, elemName); } @Override public void namespaceAfterStartElement(final String prefix, final String uri) throws SAXException { // hack for XSLTC with finding URI for default namespace if (m_elemContext.m_elementURI == null) { String prefix1 = getPrefixPart(m_elemContext.m_elementName); if (prefix1 == null && EMPTYSTRING.equals(prefix)) { // the elements URI is not known yet, and it // doesn't have a prefix, and we are currently // setting the uri for prefix "", so we have // the uri for the element... lets remember it m_elemContext.m_elementURI = uri; } } startPrefixMapping(prefix, uri, false); return; } /** * From XSLTC * Declare a prefix to point to a namespace URI. Inform SAX handler * if this is a new prefix mapping. * @param prefix prefix * @param uri uri * @return boolean */ protected boolean pushNamespace(String prefix, String uri) { try { if (m_prefixMap.pushNamespace( prefix, uri, m_elemContext.m_currentElemDepth)) { startPrefixMapping(prefix, uri); return true; } } catch (SAXException e) { // falls through } return false; } @Override public boolean reset() { boolean wasReset = false; if (super.reset()) { // Make this call when resetToXMLStream does // something. // resetToXMLStream(); wasReset = true; } return wasReset; } /** * Reset all of the fields owned by ToStream class. */ private void resetToXMLStream() { // This is an empty method, but is kept for future use // as a place holder for a location to reset fields // defined within this class return; } /** * This method checks for the XML version of output document. * If XML version of output document is not specified, then output * document is of version XML 1.0. * If XML version of output doucment is specified, but it is not either * XML 1.0 or XML 1.1, a warning message is generated, the XML Version of * output document is set to XML 1.0 and processing continues. * @return string (XML version) */ private String getXMLVersion() { String xmlVersion = getVersion(); if (xmlVersion == null || xmlVersion.equals(XMLVERSION10)) { xmlVersion = XMLVERSION10; } else if (xmlVersion.equals(XMLVERSION11)) { xmlVersion = XMLVERSION11; } else { String msg = Utils.messages.createMessage( MsgKey.ER_XML_VERSION_NOT_SUPPORTED, new Object[]{xmlVersion}); try { // Prepare to issue the warning message Transformer tran = super.getTransformer(); ErrorListener errHandler = tran.getErrorListener(); // Issue the warning message if (null != errHandler && m_sourceLocator != null) { errHandler.warning(new TransformerException(msg, m_sourceLocator)); } else { MLogger.inf(msg); } } catch (Exception e) { } xmlVersion = XMLVERSION10; } return xmlVersion; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy