src/com/sun/org/apache/xml/internal/serializer/SerializerBase.java

Print this page

        

*** 1,13 **** /* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* ! * Copyright 2001-2004 The Apache Software Foundation. ! * ! * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * --- 1,15 ---- /* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* ! * 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 *
*** 21,32 **** * $Id: SerializerBase.java,v 1.5 2006/04/14 12:09:19 sunithareddy Exp $ */ package com.sun.org.apache.xml.internal.serializer; import java.io.IOException; ! import java.util.Vector; import javax.xml.transform.SourceLocator; import javax.xml.transform.Transformer; import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; import com.sun.org.apache.xml.internal.serializer.utils.Utils; --- 23,37 ---- * $Id: SerializerBase.java,v 1.5 2006/04/14 12:09:19 sunithareddy Exp $ */ package com.sun.org.apache.xml.internal.serializer; import java.io.IOException; ! import java.util.HashMap; ! import java.util.Set; ! import java.util.ArrayList; + import javax.xml.transform.OutputKeys; import javax.xml.transform.SourceLocator; import javax.xml.transform.Transformer; import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; import com.sun.org.apache.xml.internal.serializer.utils.Utils;
*** 106,138 **** protected boolean m_inExternalDTD = false; /** * The System ID for the doc type. */ ! private String m_doctypeSystem; /** * The public ID for the doc type. */ ! private String m_doctypePublic; /** * Flag to tell that we need to add the doctype decl, which we can't do * until the first element is encountered. */ boolean m_needToOutputDocTypeDecl = true; /** - * The character encoding. Must match the encoding used for the - * printWriter. - */ - private String m_encoding = null; - - /** * Tells if we should write the XML declaration. */ ! private boolean m_shouldNotWriteXMLHeader = false; /** * The standalone value for the doctype. */ private String m_standalone; --- 111,137 ---- protected boolean m_inExternalDTD = false; /** * The System ID for the doc type. */ ! protected String m_doctypeSystem; /** * The public ID for the doc type. */ ! protected String m_doctypePublic; /** * Flag to tell that we need to add the doctype decl, which we can't do * until the first element is encountered. */ boolean m_needToOutputDocTypeDecl = true; /** * Tells if we should write the XML declaration. */ ! protected boolean m_shouldNotWriteXMLHeader = false; /** * The standalone value for the doctype. */ private String m_standalone;
*** 157,187 **** protected int m_indentAmount = 0; /** * Tells the XML version, for writing out to the XML decl. */ ! private String m_version = null; /** * The mediatype. Not used right now. */ ! private String m_mediatype; /** * The transformer that was around when this output handler was created (if * any). */ private Transformer m_transformer; /** - * Pairs of local names and corresponding URIs of CDATA sections. This list - * comes from the cdata-section-elements attribute. Every second one is a - * local name, and every other second one is the URI for the local name. - */ - protected Vector m_cdataSectionElements = null; - - /** * Namespace support, that keeps track of currently defined * prefix/uri mappings. As processed elements come and go, so do * the associated mappings for that element. */ protected NamespaceMappings m_prefixMap; --- 156,179 ---- protected int m_indentAmount = 0; /** * Tells the XML version, for writing out to the XML decl. */ ! protected String m_version = null; /** * The mediatype. Not used right now. */ ! protected String m_mediatype; /** * The transformer that was around when this output handler was created (if * any). */ private Transformer m_transformer; /** * Namespace support, that keeps track of currently defined * prefix/uri mappings. As processed elements come and go, so do * the associated mappings for that element. */ protected NamespaceMappings m_prefixMap;
*** 536,565 **** * Returns the character encoding to be used in the output document. * @return the character encoding to be used in the output document. */ public String getEncoding() { ! return m_encoding; } /** * Sets the character encoding coming from the xsl:output encoding stylesheet attribute. * @param m_encoding the character encoding */ ! public void setEncoding(String m_encoding) { ! this.m_encoding = m_encoding; } /** * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute * @param b true if the XML declaration is to be omitted from the output * document. */ public void setOmitXMLDeclaration(boolean b) { ! this.m_shouldNotWriteXMLHeader = b; } /** * @return true if the XML declaration is to be omitted from the output --- 528,558 ---- * Returns the character encoding to be used in the output document. * @return the character encoding to be used in the output document. */ public String getEncoding() { ! return getOutputProperty(OutputKeys.ENCODING); } /** * Sets the character encoding coming from the xsl:output encoding stylesheet attribute. * @param m_encoding the character encoding */ ! public void setEncoding(String encoding) { ! setOutputProperty(OutputKeys.ENCODING,encoding); } /** * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute * @param b true if the XML declaration is to be omitted from the output * document. */ public void setOmitXMLDeclaration(boolean b) { ! String val = b ? "yes":"no"; ! setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,val); } /** * @return true if the XML declaration is to be omitted from the output
*** 586,596 **** * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypePublic(String doctypePublic) { ! this.m_doctypePublic = doctypePublic; } /** * Returns the previously set value of the value to be used --- 579,589 ---- * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypePublic(String doctypePublic) { ! setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctypePublic); } /** * Returns the previously set value of the value to be used
*** 608,630 **** * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypeSystem(String doctypeSystem) { ! this.m_doctypeSystem = doctypeSystem; } /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctype(String doctypeSystem, String doctypePublic) { ! this.m_doctypeSystem = doctypeSystem; ! this.m_doctypePublic = doctypePublic; } /** * Sets the value coming from the xsl:output standalone stylesheet attribute. * @param standalone a value of "yes" indicates that the --- 601,623 ---- * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypeSystem(String doctypeSystem) { ! setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem); } /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctype(String doctypeSystem, String doctypePublic) { ! setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem); ! setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctypePublic); } /** * Sets the value coming from the xsl:output standalone stylesheet attribute. * @param standalone a value of "yes" indicates that the
*** 632,647 **** * document. This method remembers if the value was explicitly set using * this method, verses if the value is the default value. */ public void setStandalone(String standalone) { ! if (standalone != null) ! { ! m_standaloneWasSpecified = true; ! setStandaloneInternal(standalone); ! } } /** * Sets the XSL standalone attribute, but does not remember if this is a * default or explicite setting. * @param standalone "yes" | "no" */ --- 625,637 ---- * document. This method remembers if the value was explicitly set using * this method, verses if the value is the default value. */ public void setStandalone(String standalone) { ! setOutputProperty(OutputKeys.STANDALONE, standalone); } + /** * Sets the XSL standalone attribute, but does not remember if this is a * default or explicite setting. * @param standalone "yes" | "no" */
*** 698,708 **** * @param version the version of the output format. * @see SerializationHandler#setVersion(String) */ public void setVersion(String version) { ! m_version = version; } /** * Sets the value coming from the xsl:output media-type stylesheet attribute. * @param mediaType the non-null media-type or MIME type associated with the --- 688,698 ---- * @param version the version of the output format. * @see SerializationHandler#setVersion(String) */ public void setVersion(String version) { ! setOutputProperty(OutputKeys.VERSION, version); } /** * Sets the value coming from the xsl:output media-type stylesheet attribute. * @param mediaType the non-null media-type or MIME type associated with the
*** 710,720 **** * @see javax.xml.transform.OutputKeys#MEDIA_TYPE * @see SerializationHandler#setMediaType(String) */ public void setMediaType(String mediaType) { ! m_mediatype = mediaType; } /** * @return the number of spaces to indent for each indentation level. */ --- 700,710 ---- * @see javax.xml.transform.OutputKeys#MEDIA_TYPE * @see SerializationHandler#setMediaType(String) */ public void setMediaType(String mediaType) { ! setOutputProperty(OutputKeys.MEDIA_TYPE,mediaType); } /** * @return the number of spaces to indent for each indentation level. */
*** 739,749 **** * visually indicate its structure. * @see XSLOutputAttributes#setIndent(boolean) */ public void setIndent(boolean doIndent) { ! m_doIndent = doIndent; } /** * Sets the isStandalone property * @param isStandalone true if the ORACLE_IS_STANDALONE is set to yes --- 729,740 ---- * visually indicate its structure. * @see XSLOutputAttributes#setIndent(boolean) */ public void setIndent(boolean doIndent) { ! String val = doIndent ? "yes":"no"; ! setOutputProperty(OutputKeys.INDENT,val); } /** * Sets the isStandalone property * @param isStandalone true if the ORACLE_IS_STANDALONE is set to yes
*** 785,847 **** { return this; } /** - * Push a boolean state based on if the name of the current element - * is found in the list of qnames. A state is only pushed if - * there were some cdata-section-names were specified. - * <p> - * Hidden parameters are the vector of qualified elements specified in - * cdata-section-names attribute, and the m_cdataSectionStates stack - * onto which whether the current element is in the list is pushed (true or - * false). Other hidden parameters are the current elements namespaceURI, - * localName and qName - */ - protected boolean isCdataSection() - { - - boolean b = false; - - if (null != m_cdataSectionElements) - { - if (m_elemContext.m_elementLocalName == null) - m_elemContext.m_elementLocalName = - getLocalName(m_elemContext.m_elementName); - if (m_elemContext.m_elementURI == null) - { - String prefix = getPrefixPart(m_elemContext.m_elementName); - if (prefix != null) - m_elemContext.m_elementURI = - m_prefixMap.lookupNamespace(prefix); - - } - - if ((null != m_elemContext.m_elementURI) - && m_elemContext.m_elementURI.length() == 0) - m_elemContext.m_elementURI = null; - - int nElems = m_cdataSectionElements.size(); - - // loop through 2 at a time, as these are pairs of URI and localName - for (int i = 0; i < nElems; i += 2) - { - String uri = (String) m_cdataSectionElements.elementAt(i); - String loc = (String) m_cdataSectionElements.elementAt(i + 1); - if (loc.equals(m_elemContext.m_elementLocalName) - && subPartMatch(m_elemContext.m_elementURI, uri)) - { - b = true; - - break; - } - } - } - return b; - } - - /** * Tell if two strings are equal, without worry if the first string is null. * * @param p String reference, which may be null. * @param t String reference, which may be null. * --- 776,785 ----
*** 1310,1325 **** * */ private void resetSerializerBase() { this.m_attributes.clear(); ! this.m_cdataSectionElements = null; this.m_elemContext = new ElemContext(); this.m_doctypePublic = null; this.m_doctypeSystem = null; this.m_doIndent = false; - this.m_encoding = null; this.m_indentAmount = 0; this.m_inEntityRef = false; this.m_inExternalDTD = false; this.m_mediatype = null; this.m_needToCallStartDocument = true; --- 1248,1262 ---- * */ private void resetSerializerBase() { this.m_attributes.clear(); ! this.m_StringOfCDATASections = null; this.m_elemContext = new ElemContext(); this.m_doctypePublic = null; this.m_doctypeSystem = null; this.m_doIndent = false; this.m_indentAmount = 0; this.m_inEntityRef = false; this.m_inExternalDTD = false; this.m_mediatype = null; this.m_needToCallStartDocument = true;
*** 1397,1402 **** --- 1334,1668 ---- public void setDTDEntityExpansion(boolean expand) { // This method just provides a definition to satisfy the interface // A particular sub-class of SerializerBase provides the implementation (if desired) } + + /** + * The CDATA section names stored in a whitespace separateed list with + * each element being a word of the form "{uri}localName" This list + * comes from the cdata-section-elements attribute. + * + * This field replaces m_cdataSectionElements Vector. + */ + protected String m_StringOfCDATASections = null; + + boolean m_docIsEmpty = true; + void initCdataElems(String s) + { + if (s != null) + { + int max = s.length(); + + // true if we are in the middle of a pair of curly braces that delimit a URI + boolean inCurly = false; + + // true if we found a URI but haven't yet processed the local name + boolean foundURI = false; + + StringBuilder buf = new StringBuilder(); + String uri = null; + String localName = null; + + // parse through string, breaking on whitespaces. I do this instead + // of a tokenizer so I can track whitespace inside of curly brackets, + // which theoretically shouldn't happen if they contain legal URLs. + for (int i = 0; i < max; i++) + { + char c = s.charAt(i); + + if (Character.isWhitespace(c)) + { + if (!inCurly) + { + if (buf.length() > 0) + { + localName = buf.toString(); + if (!foundURI) + uri = ""; + addCDATAElement(uri,localName); + buf.setLength(0); + foundURI = false; + } + continue; + } + else + buf.append(c); // add whitespace to the URI + } + else if ('{' == c) // starting a URI + inCurly = true; + else if ('}' == c) + { + // we just ended a URI + foundURI = true; + uri = buf.toString(); + buf.setLength(0); + inCurly = false; + } + else + { + // append non-whitespace, non-curly to current URI or localName being gathered. + buf.append(c); + } + + } + + if (buf.length() > 0) + { + // We have one last localName to process. + localName = buf.toString(); + if (!foundURI) + uri = ""; + addCDATAElement(uri,localName); + } + } + } + + protected java.util.HashMap<String, HashMap<String, String>> m_CdataElems = null; + private void addCDATAElement(String uri, String localName) + { + if (m_CdataElems == null) { + m_CdataElems = new java.util.HashMap<>(); + } + + HashMap<String,String> h = m_CdataElems.get(localName); + if (h == null) { + h = new HashMap<>(); + m_CdataElems.put(localName,h); + } + h.put(uri,uri); + + } + + + /** + * Return true if nothing has been sent to this result tree yet. + * <p> + * This is not a public API. + * + * @xsl.usage internal + */ + public boolean documentIsEmpty() { + // If we haven't called startDocument() yet, then this document is empty + return m_docIsEmpty && (m_elemContext.m_currentElemDepth == 0); + } + + /** + * Return true if the current element in m_elemContext + * is a CDATA section. + * CDATA sections are specified in the <xsl:output> attribute + * cdata-section-names or in the JAXP equivalent property. + * In any case the format of the value of such a property is: + * <pre> + * "{uri1}localName1 {uri2}localName2 . . . " + * </pre> + * + * <p> + * This method is not a public API, but is only used internally by the serializer. + */ + protected boolean isCdataSection() { + boolean b = false; + + if (null != m_StringOfCDATASections) { + if (m_elemContext.m_elementLocalName == null) { + String localName = getLocalName(m_elemContext.m_elementName); + m_elemContext.m_elementLocalName = localName; + } + + if ( m_elemContext.m_elementURI == null) { + + m_elemContext.m_elementURI = getElementURI(); + } + else if ( m_elemContext.m_elementURI.length() == 0) { + if ( m_elemContext.m_elementName == null) { + m_elemContext.m_elementName = m_elemContext.m_elementLocalName; + // leave URI as "", meaning in no namespace + } + else if (m_elemContext.m_elementLocalName.length() < m_elemContext.m_elementName.length()){ + // We were told the URI was "", yet the name has a prefix since the name is longer than the localname. + // So we will fix that incorrect information here. + m_elemContext.m_elementURI = getElementURI(); + } + } + + HashMap<String, String> h = null; + if (m_CdataElems != null) { + h = m_CdataElems.get(m_elemContext.m_elementLocalName); + } + if (h != null) { + Object obj = h.get(m_elemContext.m_elementURI); + if (obj != null) + b = true; + } + + } + return b; + } + + /** + * Before this call m_elementContext.m_elementURI is null, + * which means it is not yet known. After this call it + * is non-null, but possibly "" meaning that it is in the + * default namespace. + * + * @return The URI of the element, never null, but possibly "". + */ + private String getElementURI() { + String uri = null; + // At this point in processing we have received all the + // namespace mappings + // As we still don't know the elements namespace, + // we now figure it out. + + String prefix = getPrefixPart(m_elemContext.m_elementName); + + if (prefix == null) { + // no prefix so lookup the URI of the default namespace + uri = m_prefixMap.lookupNamespace(""); + } else { + uri = m_prefixMap.lookupNamespace(prefix); + } + if (uri == null) { + // We didn't find the namespace for the + // prefix ... ouch, that shouldn't happen. + // This is a hack, we really don't know + // the namespace + uri = EMPTYSTRING; + } + + return uri; + } + + + /** + * Get the value of an output property, + * the explicit value, if any, otherwise the + * default value, if any, otherwise null. + */ + public String getOutputProperty(String name) { + String val = getOutputPropertyNonDefault(name); + // If no explicit value, try to get the default value + if (val == null) + val = getOutputPropertyDefault(name); + return val; + + } + /** + * Get the value of an output property, + * not the default value. If there is a default + * value, but no non-default value this method + * will return null. + * <p> + * + */ + public String getOutputPropertyNonDefault(String name) { + return getProp(name,false); + } + + /** + * Get the default value of an xsl:output property, + * which would be null only if no default value exists + * for the property. + */ + public String getOutputPropertyDefault(String name) { + return getProp(name, true); + } + + /** + * Set the value for the output property, typically from + * an xsl:output element, but this does not change what + * the default value is. + */ + public void setOutputProperty(String name, String val) { + setProp(name,val,false); + } + + /** + * Set the default value for an output property, but this does + * not impact any explicitly set value. + */ + public void setOutputPropertyDefault(String name, String val) { + setProp(name,val,true); + + } + + /** + * A mapping of keys to explicitly set values, for example if + * and <xsl:output/> has an "encoding" attribute, this + * map will have what that attribute maps to. + */ + private HashMap<String, String> m_OutputProps; + /** + * A mapping of keys to default values, for example if + * the default value of the encoding is "UTF-8" then this + * map will have that "encoding" maps to "UTF-8". + */ + private HashMap<String, String> m_OutputPropsDefault; + + Set<String> getOutputPropDefaultKeys() { + return m_OutputPropsDefault.keySet(); + } + Set<String> getOutputPropKeys() { + return m_OutputProps.keySet(); + } + + private String getProp(String name, boolean defaultVal) { + if (m_OutputProps == null) { + m_OutputProps = new HashMap<>(); + m_OutputPropsDefault = new HashMap<>(); + } + + String val; + if (defaultVal) + val = m_OutputPropsDefault.get(name); + else + val = m_OutputProps.get(name); + + return val; + } + /** + * + * @param name The name of the property, e.g. "{http://myprop}indent-tabs" or "indent". + * @param val The value of the property, e.g. "4" + * @param defaultVal true if this is a default value being set for the property as + * opposed to a user define on, set say explicitly in the stylesheet or via JAXP + */ + void setProp(String name, String val, boolean defaultVal) { + if (m_OutputProps == null) { + m_OutputProps = new HashMap<>(); + m_OutputPropsDefault = new HashMap<>(); + } + + if (defaultVal) + m_OutputPropsDefault.put(name,val); + else { + if (OutputKeys.CDATA_SECTION_ELEMENTS.equals(name) && val != null) { + initCdataElems(val); + String oldVal = m_OutputProps.get(name); + String newVal; + if (oldVal == null) + newVal = oldVal + ' ' + val; + else + newVal = val; + m_OutputProps.put(name,newVal); + } + else { + m_OutputProps.put(name,val); + } + } + } + + /** + * Get the first char of the local name + * @param name Either a local name, or a local name + * preceeded by a uri enclosed in curly braces. + */ + static char getFirstCharLocName(String name) { + final char first; + int i = name.indexOf('}'); + if (i < 0) + first = name.charAt(0); + else + first = name.charAt(i+1); + return first; + } }