You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by ar...@locus.apache.org on 2000/02/16 01:58:10 UTC

cvs commit: xml-xerces/java/src/org/apache/xml/serialize BaseMarkupSerializer.java ElementState.java HTMLSerializer.java Serializer.java TextSerializer.java XMLSerializer.java

arkin       00/02/15 16:58:10

  Modified:    java/src/org/apache/xml/serialize BaseMarkupSerializer.java
                        ElementState.java HTMLSerializer.java
                        Serializer.java TextSerializer.java
                        XMLSerializer.java
  Log:
  Added SAX2 support (ContentHandler) and namespace handling.
  
  Revision  Changes    Path
  1.10      +53 -27    xml-xerces/java/src/org/apache/xml/serialize/BaseMarkupSerializer.java
  
  Index: BaseMarkupSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/BaseMarkupSerializer.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- BaseMarkupSerializer.java	2000/02/08 01:20:04	1.9
  +++ BaseMarkupSerializer.java	2000/02/16 00:58:09	1.10
  @@ -120,7 +120,8 @@
    * @see DOMSerializer
    */
   public abstract class BaseMarkupSerializer
  -    implements DocumentHandler, LexicalHandler, DTDHandler, DeclHandler,
  +    implements ContentHandler, DocumentHandler, LexicalHandler,
  +	       DTDHandler, DeclHandler,
   	       DOMSerializer, Serializer
   {
   
  @@ -241,6 +242,15 @@
       private Writer          _docWriter;
   
   
  +    /**
  +     * Association between namespace URIs (keys) and prefixes (values).
  +     * Accumulated here prior to starting an element and placing this
  +     * list in the element state.
  +     */
  +    protected Hashtable     _prefixes;
  +
  +
  +
       //--------------------------------//
       // Constructor and initialization //
       //--------------------------------//
  @@ -269,7 +279,7 @@
   
       public ContentHandler asContentHandler()
       {
  -	return null;
  +	return this;
       }
   
   
  @@ -588,36 +598,21 @@
       }
       
   
  -    public void startPrefixMapping (String prefix, String uri)
  +    public void startPrefixMapping( String prefix, String uri )
   	throws SAXException
       {
  -	// Not yet supported
  +	if ( _prefixes == null )
  +	    _prefixes = new Hashtable();
  +	_prefixes.put( uri, prefix == null ? "" : prefix );
       }
   
   
  -    public void endPrefixMapping (String prefix)
  +    public void endPrefixMapping( String prefix )
   	throws SAXException
       {
  -	// Not yet supported
       }
   
   
  -    public void startElement (String namespaceURI, String localName,
  -			      String rawName, Attributes atts)
  -	throws SAXException
  -    {
  -	// Not yet supported
  -    }
  -
  -
  -    public void endElement (String namespaceURI, String localName,
  -			    String rawName)
  -	throws SAXException
  -    {
  -	// Not yet supported
  -    }
  -
  -
       //---------------------------------------//
       // SAX DTD/Decl handler serializing methods //
       //---------------------------------------//
  @@ -1428,29 +1423,34 @@
        *
        * @return Current element state, or null
        */
  -    protected ElementState enterElementState( String tagName, boolean preserveSpace )
  +    protected ElementState enterElementState( String namespaceURI, String localName,
  +					      String rawName, boolean preserveSpace )
       {
   	ElementState state;
   
   	if ( _elementStateCount == _elementStates.length ) {
   	    ElementState[] newStates;
  -	    int            i;
   
   	    // Need to create a larger array of states.
   	    // This does not happen often, unless the document
   	    // is really deep.
   	    newStates = new ElementState[ _elementStates.length + 5 ];
  -	    System.arraycopy( _elementStates, 0, newStates, 0, _elementStates.length );
  +	    for ( int i = 0 ; i < _elementStates.length ; ++i )
  +		newStates[ i ] = _elementStates[ i ];
   	    _elementStates = newStates;
  -	    for ( i = _elementStateCount ; i < _elementStates.length ; ++i )
  +	    for ( int i = _elementStateCount ; i < _elementStates.length ; ++i )
   		_elementStates[ i ] = new ElementState();
   	}
   	state = _elementStates[ _elementStateCount ];
  -	state.tagName = tagName;
  +	state.namespaceURI = namespaceURI;
  +	state.localName = localName;
  +	state.rawName = rawName;
   	state.preserveSpace = preserveSpace;
   	state.empty = true;
   	state.afterElement = false;
   	state.doCData = state.inCData = false;
  +	state.prefixes = _prefixes;
  +	_prefixes = null;
   	++_elementStateCount;
   	return state;
       }
  @@ -1467,12 +1467,38 @@
       {
   	if ( _elementStateCount > 1 ) {
   	    -- _elementStateCount;
  +	    _prefixes = _elementStates[ _elementStateCount ].prefixes;
   	    return _elementStates[ _elementStateCount - 1 ];
   	} else if ( _elementStateCount == 1 ) {
   	    -- _elementStateCount;
  +	    _prefixes = _elementStates[ _elementStateCount ].prefixes;
   	    return null;
   	} else
   	    return null;
  +    }
  +
  +
  +    protected String getPrefix( String namespaceURI )
  +    {
  +	String    prefix;
  +	
  +	if ( _prefixes != null ) {
  +	    prefix = (String) _prefixes.get( namespaceURI );
  +	    if ( prefix != null )
  +		return prefix;
  +	}
  +	if ( _elementStateCount == 0 )
  +	    return null;
  +	else {
  +	    for ( int i = _elementStateCount ; i-- > 0 ; ) {
  +		if ( _elementStates[ i ].prefixes != null ) {
  +		    prefix = (String) _elementStates[ i ].prefixes.get( namespaceURI );
  +                    if ( prefix != null )
  +			 return prefix;
  +		}
  +	    }
  +	}
  +	return null;
       }
   
   
  
  
  
  1.4       +24 -2     xml-xerces/java/src/org/apache/xml/serialize/ElementState.java
  
  Index: ElementState.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/ElementState.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ElementState.java	2000/01/28 21:41:39	1.3
  +++ ElementState.java	2000/02/16 00:58:09	1.4
  @@ -59,6 +59,9 @@
   package org.apache.xml.serialize;
   
   
  +import java.util.Hashtable;
  +
  +
   /**
    * Holds the state of the currently serialized element.
    *
  @@ -71,13 +74,25 @@
   {
   
   
  +    /**
  +     * The element's raw tag name (local or prefix:local).
  +     */
  +    String rawName;
  +
  +
       /**
  -     * The element's tag name.
  +     * The element's local tag name.
        */
  -    String tagName;
  +    String localName;
   
   
       /**
  +     * The element's namespace URI.
  +     */
  +    String namespaceURI;
  +
  +
  +    /**
        * True if element is space preserving.
        */
       boolean preserveSpace;
  @@ -114,6 +129,13 @@
        * True while inside CData and printing text as CData.
        */
       boolean inCData;
  +
  +
  +    /**
  +     * Association between namespace URIs (keys) and prefixes (values).
  +     */
  +    Hashtable prefixes;
  +
   
   
   }
  
  
  
  1.9       +217 -46   xml-xerces/java/src/org/apache/xml/serialize/HTMLSerializer.java
  
  Index: HTMLSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/HTMLSerializer.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- HTMLSerializer.java	2000/02/05 02:24:15	1.8
  +++ HTMLSerializer.java	2000/02/16 00:58:09	1.9
  @@ -63,13 +63,16 @@
   import java.io.UnsupportedEncodingException;
   import java.io.OutputStream;
   import java.io.Writer;
  +import java.util.Enumeration;
   
   import org.w3c.dom.Element;
   import org.w3c.dom.Attr;
   import org.w3c.dom.Node;
   import org.w3c.dom.NamedNodeMap;
   import org.xml.sax.DocumentHandler;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.AttributeList;
  +import org.xml.sax.Attributes;
   
   
   /**
  @@ -121,8 +124,11 @@
       private static boolean _xhtml;
   
   
  +    public static String XHTMLNamespace = "";
   
   
  +
  +
       /**
        * Constructs a new HTML/XHTML serializer depending on the value of
        * <tt>xhtml</tt>. The serializer cannot be used without calling
  @@ -202,40 +208,22 @@
   	    super.setOutputFormat( format );
       }
   
  -
  -    //------------------------------------------//
  -    // SAX document handler serializing methods //
  -    //------------------------------------------//
  -
  -
  -    public void characters( char[] chars, int start, int length )
  -    {
  - 	ElementState state;
   
  -	// HTML: no CDATA section
  -	state = content();
  -	if ( state != null )
  -	    state.doCData = false;
  -	super.characters( chars, start, length );
  -    }
  +    //-----------------------------------------//
  +    // SAX content handler serializing methods //
  +    //-----------------------------------------//
   
   
  -    public void startDocument()
  +    public void startElement( String namespaceURI, String localName,
  +			      String rawName, Attributes attrs )
       {
  -	// Do nothing for HTML/XHTML, browser might not respond
  -	// well to <?xml ...?>
  -	if ( _writer == null )
  -	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  -    }
  -
  -
  -    public void startElement( String tagName, AttributeList attrs )
  -    {
   	int          i;
   	boolean      preserveSpace;
   	ElementState state;
   	String       name;
   	String       value;
  +	String       htmlName;
  +	boolean      addNSAttr = false;
   
   	if ( _writer == null )
   	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  @@ -247,7 +235,7 @@
   	    // the document's DOCTYPE. Space preserving defaults
   	    // to that of the output format.
   	    if ( ! _started )
  -		startDocument( tagName );
  +		startDocument( localName == null ? rawName : localName );
   	    preserveSpace = _format.getPreserveSpace();
   	} else {
   	    // For any other element, if first in parent, then
  @@ -266,11 +254,31 @@
   	// Do not change the current element state yet.
   	// This only happens in endElement().
   
  +	if ( rawName == null ) {
  +	    rawName = localName;
  +	    if ( namespaceURI != null ) {
  +		String prefix;
  +		prefix = getPrefix( namespaceURI );
  +		if ( prefix.length() > 0 )
  +		    rawName = prefix + ":" + localName;
  +	    }
  +	    addNSAttr = true;
  +	}
  +	if ( namespaceURI == null )
  +	    htmlName = rawName;
  +	else {
  +	    if ( namespaceURI.equals( XHTMLNamespace ) )
  +		htmlName = localName;
  +	    else
  +		htmlName = null;
  +	}
  +	    
  +
   	// XHTML: element names are lower case, DOM will be different
   	if ( _xhtml )
  -	    printText( '<' + tagName.toLowerCase() );
  +	    printText( '<' + rawName.toLowerCase() );
   	else
  -	    printText( '<' + tagName );
  +	    printText( '<' + rawName );
   	indent();
   
   	// For each attribute serialize it's name and value as one part,
  @@ -279,9 +287,9 @@
   	if ( attrs != null ) {
   	    for ( i = 0 ; i < attrs.getLength() ; ++i ) {
   		printSpace();
  -		name = attrs.getName( i ).toLowerCase();;
  +		name = attrs.getRawName( i ).toLowerCase();;
   		value = attrs.getValue( i );
  -		if ( _xhtml ) {
  +		if ( _xhtml || namespaceURI != null ) {
   		    // XHTML: print empty string for null values.
   		    if ( value == null )
   			printText( name + "=\"\"" );
  @@ -292,25 +300,42 @@
   		    // HTML: URI attributes will print unescaped
   		    if ( value == null || value.length() == 0 )
   			printText( name );
  -		    else if ( HTMLdtd.isURI( tagName, name ) )
  +		    else if ( HTMLdtd.isURI( rawName, name ) )
   			printText( name + "=\"" + escapeURI( value ) + '"' );
  -		    else if ( HTMLdtd.isBoolean( tagName, name ) )
  +		    else if ( HTMLdtd.isBoolean( rawName, name ) )
   			printText( name );
   		    else
   			printText( name + "=\"" + escape( value ) + '"' );
   		}
   	    }
   	}
  -	if ( HTMLdtd.isPreserveSpace( tagName ) )
  +	if ( htmlName != null && HTMLdtd.isPreserveSpace( htmlName ) )
   	    preserveSpace = true;
   
  +	if ( addNSAttr ) {
  +	    Enumeration enum;
  +	    
  +	    enum = _prefixes.keys();
  +	    while ( enum.hasMoreElements() ) {
  +		printSpace();
  +		value = (String) enum.nextElement();
  +		name = (String) _prefixes.get( value );
  +		if ( name.length() == 0 )
  +		    printText( "xmlns=\"" + value + '"' );
  +		else
  +		    printText( "xmlns:" + name + "=\"" + value + '"' );
  +	    }
  +	}
  +
   	// Now it's time to enter a new element state
   	// with the tag name and space preserving.
   	// We still do not change the curent element state.
  -	state = enterElementState( tagName, preserveSpace );
  +	state = enterElementState( namespaceURI, localName, rawName, preserveSpace );
   
   	// Prevents line breaks inside A/TD
  -	if ( tagName.equalsIgnoreCase( "A" ) || tagName.equalsIgnoreCase( "TD" ) ) {
  +
  +	if ( htmlName != null && ( htmlName.equalsIgnoreCase( "A" ) ||
  +				   htmlName.equalsIgnoreCase( "TD" ) ) ) {
   	    state.empty = false;
   	    printText( ">" );
   	}
  @@ -318,8 +343,8 @@
   	// Handle SCRIPT and STYLE specifically by changing the
   	// state of the current element to CDATA (XHTML) or
   	// unescaped (HTML).
  -	if ( tagName.equalsIgnoreCase( "SCRIPT" ) ||
  -	     tagName.equalsIgnoreCase( "STYLE" ) ) {
  +	if ( htmlName != null && ( rawName.equalsIgnoreCase( "SCRIPT" ) ||
  +				   rawName.equalsIgnoreCase( "STYLE" ) ) ) {
   	    if ( _xhtml ) {
   		// XHTML: Print contents as CDATA section
   		state.doCData = true;
  @@ -331,15 +356,27 @@
       }
   
   
  -    public void endElement( String tagName )
  +    public void endElement( String namespaceURI, String localName,
  +			    String rawName )
       {
   	ElementState state;
  +	String       htmlName;
   
   	// Works much like content() with additions for closing
   	// an element. Note the different checks for the closed
   	// element's state and the parent element's state.
   	unindent();
   	state = getElementState();
  +
  +	if ( state.namespaceURI == null )
  +	    htmlName = state.rawName;
  +	else {
  +	    if ( state.namespaceURI.equals( XHTMLNamespace ) )
  +		htmlName = state.localName;
  +	    else
  +		htmlName = null;
  +	}
  +
   	if ( _xhtml) {
   	    if ( state.empty ) {
   		printText( " />" );
  @@ -348,7 +385,7 @@
   		if ( state.inCData )
   		    printText( "]]>" );
   		// XHTML: element names are lower case, DOM will be different
  -		printText( "</" + tagName.toLowerCase() + ">" );
  +		printText( "</" + state.rawName.toLowerCase() + ">" );
   	    }
   	} else {
   	    if ( state.empty )
  @@ -358,13 +395,13 @@
   	    // last element and this element's closing tag.
   	    // [keith] Provided this is not an anchor.
   	    // HTML: some elements do not print closing tag (e.g. LI)
  -	    if ( ! HTMLdtd.isOnlyOpening( tagName ) ) {
  +	    if ( htmlName == null || ! HTMLdtd.isOnlyOpening( htmlName ) ) {
   		if ( _format.getIndenting() && ! state.preserveSpace && state.afterElement )
   		    breakLine();
   		// Must leave CData section first (Illegal in HTML, but still)
   		if ( state.inCData )
   		    printText( "]]>" );
  -		printText( "</" + tagName + ">" );
  +		printText( "</" + state.rawName + ">" );
   	    }
   	}
   	// Leave the element state and update that of the parent
  @@ -372,11 +409,11 @@
   	state = leaveElementState();
   	if ( state != null ) {
   	    // Temporary hack to prevent line breaks inside A/TD
  -	    if ( ! state.tagName.equalsIgnoreCase( "A" ) && ! state.tagName.equalsIgnoreCase( "TD" ) )
  +	    if ( htmlName == null || ( ! htmlName.equalsIgnoreCase( "A" ) &&
  +				       ! htmlName.equalsIgnoreCase( "TD" ) ) )
  +
   		state.afterElement = true;
  -	    // state.afterElement = true;
   	    state.empty = false;
  -	    // Temporary hack to prevent line breaks inside A/TD
   	} else {
   	    // [keith] If we're done printing the document but don't
   	    // get to call endDocument(), the buffer should be flushed.
  @@ -386,6 +423,140 @@
   
   
       //------------------------------------------//
  +    // SAX document handler serializing methods //
  +    //------------------------------------------//
  +
  +
  +    public void characters( char[] chars, int start, int length )
  +    {
  + 	ElementState state;
  +
  +	// HTML: no CDATA section
  +	state = content();
  +	if ( state != null )
  +	    state.doCData = false;
  +	super.characters( chars, start, length );
  +    }
  +
  +
  +    public void startDocument()
  +    {
  +	// Do nothing for HTML/XHTML, browser might not respond
  +	// well to <?xml ...?>
  +	if ( _writer == null )
  +	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  +    }
  +
  +
  +    public void startElement( String tagName, AttributeList attrs )
  +    {
  +	int          i;
  +	boolean      preserveSpace;
  +	ElementState state;
  +	String       name;
  +	String       value;
  +
  +	if ( _writer == null )
  +	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  +
  +	state = getElementState();
  +	if ( state == null ) {
  +	    // If this is the root element handle it differently.
  +	    // If the first root element in the document, serialize
  +	    // the document's DOCTYPE. Space preserving defaults
  +	    // to that of the output format.
  +	    if ( ! _started )
  +		startDocument( tagName );
  +	    preserveSpace = _format.getPreserveSpace();
  +	} else {
  +	    // For any other element, if first in parent, then
  +	    // close parent's opening tag and use the parnet's
  +	    // space preserving.
  +	    if ( state.empty )
  +		printText( ">" );
  +	    preserveSpace = state.preserveSpace;
  +	    // Indent this element on a new line if the first
  +	    // content of the parent element or immediately
  +	    // following an element.
  +	    if ( _format.getIndenting() && ! state.preserveSpace &&
  +		 ( state.empty || state.afterElement ) )
  +		breakLine();
  +	}
  +	// Do not change the current element state yet.
  +	// This only happens in endElement().
  +
  +	// XHTML: element names are lower case, DOM will be different
  +	if ( _xhtml )
  +	    printText( '<' + tagName.toLowerCase() );
  +	else
  +	    printText( '<' + tagName );
  +	indent();
  +
  +	// For each attribute serialize it's name and value as one part,
  +	// separated with a space so the element can be broken on
  +	// multiple lines.
  +	if ( attrs != null ) {
  +	    for ( i = 0 ; i < attrs.getLength() ; ++i ) {
  +		printSpace();
  +		name = attrs.getName( i ).toLowerCase();;
  +		value = attrs.getValue( i );
  +		if ( _xhtml ) {
  +		    // XHTML: print empty string for null values.
  +		    if ( value == null )
  +			printText( name + "=\"\"" );
  +		    else
  +			printText( name + "=\"" + escape( value ) + '"' );
  +		} else {
  +		    // HTML: Empty values print as attribute name, no value.
  +		    // HTML: URI attributes will print unescaped
  +		    if ( value == null || value.length() == 0 )
  +			printText( name );
  +		    else if ( HTMLdtd.isURI( tagName, name ) )
  +			printText( name + "=\"" + escapeURI( value ) + '"' );
  +		    else if ( HTMLdtd.isBoolean( tagName, name ) )
  +			printText( name );
  +		    else
  +			printText( name + "=\"" + escape( value ) + '"' );
  +		}
  +	    }
  +	}
  +	if ( HTMLdtd.isPreserveSpace( tagName ) )
  +	    preserveSpace = true;
  +
  +	// Now it's time to enter a new element state
  +	// with the tag name and space preserving.
  +	// We still do not change the curent element state.
  +	state = enterElementState( null, null, tagName, preserveSpace );
  +
  +	// Prevents line breaks inside A/TD
  +	if ( tagName.equalsIgnoreCase( "A" ) || tagName.equalsIgnoreCase( "TD" ) ) {
  +	    state.empty = false;
  +	    printText( ">" );
  +	}
  +
  +	// Handle SCRIPT and STYLE specifically by changing the
  +	// state of the current element to CDATA (XHTML) or
  +	// unescaped (HTML).
  +	if ( tagName.equalsIgnoreCase( "SCRIPT" ) ||
  +	     tagName.equalsIgnoreCase( "STYLE" ) ) {
  +	    if ( _xhtml ) {
  +		// XHTML: Print contents as CDATA section
  +		state.doCData = true;
  +	    } else {
  +		// HTML: Print contents unescaped
  +		state.unescaped = true;
  +	    }
  +	}
  +    }
  +
  +
  +    public void endElement( String tagName )
  +    {
  +	endElement( null, null, tagName );
  +    }
  +
  +
  +    //------------------------------------------//
       // Generic node serializing methods methods //
       //------------------------------------------//
   
  @@ -552,7 +723,7 @@
   	if ( elem.hasChildNodes() || ! HTMLdtd.isEmptyTag( tagName ) ) {
   	    // Enter an element state, and serialize the children
   	    // one by one. Finally, end the element.
  -	    state = enterElementState( tagName, preserveSpace );
  +	    state = enterElementState( null, null, tagName, preserveSpace );
   
   	    // Prevents line breaks inside A/TD
   	    if ( tagName.equalsIgnoreCase( "A" ) || tagName.equalsIgnoreCase( "TD" ) ) {
  @@ -578,7 +749,7 @@
   		serializeNode( child );
   		child = child.getNextSibling();
   	    }
  -	    endElement( tagName );
  +	    endElement( null, null, tagName );
   	} else {
   	    unindent();
   	    // XHTML: Close empty tag with ' />' so it's XML and HTML compatible.
  
  
  
  1.6       +0 -2      xml-xerces/java/src/org/apache/xml/serialize/Serializer.java
  
  Index: Serializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/Serializer.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Serializer.java	2000/02/08 01:20:04	1.5
  +++ Serializer.java	2000/02/16 00:58:09	1.6
  @@ -152,9 +152,7 @@
        * If the serializer does not support the {@link ContentHandler}
        * interface, it should return null.
        */
  -    /*
       public ContentHandler asContentHandler();
  -    */
   
   
       /**
  
  
  
  1.4       +22 -2     xml-xerces/java/src/org/apache/xml/serialize/TextSerializer.java
  
  Index: TextSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/TextSerializer.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TextSerializer.java	2000/01/14 20:40:54	1.3
  +++ TextSerializer.java	2000/02/16 00:58:09	1.4
  @@ -66,7 +66,9 @@
   
   import org.w3c.dom.*;
   import org.xml.sax.DocumentHandler;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.AttributeList;
  +import org.xml.sax.Attributes;
   
   
   /**
  @@ -162,7 +164,25 @@
       }
   
   
  +    //-----------------------------------------//
  +    // SAX content handler serializing methods //
  +    //-----------------------------------------//
   
  +
  +    public void startElement( String namespaceURI, String localName,
  +			      String rawName, Attributes attrs )
  +    {
  +	startElement( rawName == null ? localName : rawName, null );
  +    }
  +
  +
  +    public void endElement( String namespaceURI, String localName,
  +			    String rawName )
  +    {
  +	endElement( rawName == null ? localName : rawName );
  +    }
  +
  +
       //------------------------------------------//
       // SAX document handler serializing methods //
       //------------------------------000---------//
  @@ -202,7 +222,7 @@
   	// Now it's time to enter a new element state
   	// with the tag name and space preserving.
   	// We still do not change the curent element state.
  -	state = enterElementState( tagName, preserveSpace );
  +	state = enterElementState( null, null, tagName, preserveSpace );
       }
   
   
  @@ -325,7 +345,7 @@
   	if ( elem.hasChildNodes() ) {
   	    // Enter an element state, and serialize the children
   	    // one by one. Finally, end the element.
  -	    state = enterElementState( tagName, preserveSpace );
  +	    state = enterElementState( null, null, tagName, preserveSpace );
   	    child = elem.getFirstChild();
   	    while ( child != null ) {
   		serializeNode( child );
  
  
  
  1.9       +154 -22   xml-xerces/java/src/org/apache/xml/serialize/XMLSerializer.java
  
  Index: XMLSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xml/serialize/XMLSerializer.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- XMLSerializer.java	2000/02/05 02:24:15	1.8
  +++ XMLSerializer.java	2000/02/16 00:58:09	1.9
  @@ -63,10 +63,13 @@
   import java.io.UnsupportedEncodingException;
   import java.io.OutputStream;
   import java.io.Writer;
  +import java.util.Enumeration;
   
   import org.w3c.dom.*;
   import org.xml.sax.DocumentHandler;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.AttributeList;
  +import org.xml.sax.Attributes;
   
   
   /**
  @@ -168,27 +171,20 @@
       }
   
   
  +    //-----------------------------------------//
  +    // SAX content handler serializing methods //
  +    //-----------------------------------------//
   
  -    //------------------------------------------//
  -    // SAX document handler serializing methods //
  -    //------------------------------000---------//
   
  -
  -    public void startDocument()
  +    public void startElement( String namespaceURI, String localName,
  +			      String rawName, Attributes attrs )
       {
  -	if ( _writer == null )
  -	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  -	// Nothing to do here. All the magic happens in startDocument(String)
  -    }
  -
  -
  -    public void startElement( String tagName, AttributeList attrs )
  -    {
   	int          i;
   	boolean      preserveSpace;
   	ElementState state;
   	String       name;
   	String       value;
  +	boolean      addNSAttr = false;
   
   	if ( _writer == null )
   	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  @@ -200,7 +196,7 @@
   	    // the document's DOCTYPE. Space preserving defaults
   	    // to that of the output format.
   	    if ( ! _started )
  -		startDocument( tagName );
  +		startDocument( localName == null ? rawName : localName );
   	    preserveSpace = _format.getPreserveSpace();
   	} else {
   	    // For any other element, if first in parent, then
  @@ -219,7 +215,18 @@
   	// Do not change the current element state yet.
   	// This only happens in endElement().
   
  -	printText( '<' + tagName );
  +	if ( rawName == null ) {
  +	    rawName = localName;
  +	    if ( namespaceURI != null ) {
  +		String prefix;
  +		prefix = getPrefix( namespaceURI );
  +		if ( prefix.length() > 0 )
  +		    rawName = prefix + ":" + localName;
  +	    }
  +	    addNSAttr = true;
  +	}
  +
  +	printText( '<' + rawName );
   	indent();
   
   	// For each attribute print it's name and value as one part,
  @@ -228,7 +235,22 @@
   	if ( attrs != null ) {
   	    for ( i = 0 ; i < attrs.getLength() ; ++i ) {
   		printSpace();
  -		name = attrs.getName( i );
  +
  +		name = attrs.getRawName( i );
  +		if ( name == null ) {
  +		    String prefix;
  +		    String attrURI;
  +
  +		    name = attrs.getLocalName( i );
  +		    attrURI = attrs.getURI( i );
  +		    if ( attrURI != null && ( namespaceURI == null ||
  +					      ! attrURI.equals( namespaceURI ) ) ) {
  +			prefix = getPrefix( attrURI );
  +			if ( prefix != null && prefix.length() > 0 )
  +			    name = prefix + ":" + name;
  +		    }
  +		}
  +
   		value = attrs.getValue( i );
   		if ( value == null )
   		    value = "";
  @@ -245,16 +267,35 @@
   		}
   	    }
   	}
  +
  +	if ( addNSAttr ) {
  +	    Enumeration enum;
  +	    
  +	    enum = _prefixes.keys();
  +	    while ( enum.hasMoreElements() ) {
  +		printSpace();
  +		value = (String) enum.nextElement();
  +		name = (String) _prefixes.get( value );
  +		if ( name.length() == 0 )
  +		    printText( "xmlns=\"" + value + '"' );
  +		else
  +		    printText( "xmlns:" + name + "=\"" + value + '"' );
  +	    }
  +	}
  +
   	// Now it's time to enter a new element state
   	// with the tag name and space preserving.
   	// We still do not change the curent element state.
  -	state = enterElementState( tagName, preserveSpace );
  -	state.doCData = _format.isCDataElement( tagName );
  -	state.unescaped = _format.isNonEscapingElement( tagName );
  +	state = enterElementState( namespaceURI, localName, rawName, preserveSpace );
  +	state.doCData = _format.isCDataElement( namespaceURI == null ? rawName :
  +						namespaceURI + "^" + localName );
  +	state.unescaped = _format.isNonEscapingElement( namespaceURI == null ? rawName :
  +							namespaceURI + "^" + localName );
       }
   
   
  -    public void endElement( String tagName )
  +    public void endElement( String namespaceURI, String localName,
  +			    String rawName )
       {
   	ElementState state;
   
  @@ -274,7 +315,7 @@
   	    // last element and this element's closing tag.
   	    if ( _format.getIndenting() && ! state.preserveSpace && state.afterElement )
   		breakLine();
  -	    printText( "</" + tagName + ">" );
  +	    printText( "</" + state.rawName + ">" );
   	}
   	// Leave the element state and update that of the parent
   	// (if we're not root) to not empty and after element.
  @@ -290,6 +331,97 @@
       }
   
   
  +    //------------------------------------------//
  +    // SAX document handler serializing methods //
  +    //------------------------------------------//
  +
  +
  +    public void startDocument()
  +    {
  +	if ( _writer == null )
  +	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  +	// Nothing to do here. All the magic happens in startDocument(String)
  +    }
  +
  +
  +    public void startElement( String tagName, AttributeList attrs )
  +    {
  +	int          i;
  +	boolean      preserveSpace;
  +	ElementState state;
  +	String       name;
  +	String       value;
  +
  +	if ( _writer == null )
  +	    throw new IllegalStateException( "SER002 No writer supplied for serializer" );
  +
  +	state = getElementState();
  +	if ( state == null ) {
  +	    // If this is the root element handle it differently.
  +	    // If the first root element in the document, serialize
  +	    // the document's DOCTYPE. Space preserving defaults
  +	    // to that of the output format.
  +	    if ( ! _started )
  +		startDocument( tagName );
  +	    preserveSpace = _format.getPreserveSpace();
  +	} else {
  +	    // For any other element, if first in parent, then
  +	    // close parent's opening tag and use the parnet's
  +	    // space preserving.
  +	    if ( state.empty )
  +		printText( ">" );
  +	    preserveSpace = state.preserveSpace;
  +	    // Indent this element on a new line if the first
  +	    // content of the parent element or immediately
  +	    // following an element.
  +	    if ( _format.getIndenting() && ! state.preserveSpace &&
  +		 ( state.empty || state.afterElement ) )
  +		breakLine();
  +	}
  +	// Do not change the current element state yet.
  +	// This only happens in endElement().
  +
  +	printText( '<' + tagName );
  +	indent();
  +
  +	// For each attribute print it's name and value as one part,
  +	// separated with a space so the element can be broken on
  +	// multiple lines.
  +	if ( attrs != null ) {
  +	    for ( i = 0 ; i < attrs.getLength() ; ++i ) {
  +		printSpace();
  +		name = attrs.getName( i );
  +		value = attrs.getValue( i );
  +		if ( value == null )
  +		    value = "";
  +		printText( name + "=\"" + escape( value ) + '"' );
  +		
  +		// If the attribute xml:space exists, determine whether
  +		// to preserve spaces in this and child nodes based on
  +		// its value.
  +		if ( name.equals( "xml:space" ) ) {
  +		    if ( value.equals( "preserve" ) )
  +			preserveSpace = true;
  +		    else
  +			preserveSpace = _format.getPreserveSpace();
  +		}
  +	    }
  +	}
  +	// Now it's time to enter a new element state
  +	// with the tag name and space preserving.
  +	// We still do not change the curent element state.
  +	state = enterElementState( null, null, tagName, preserveSpace );
  +	state.doCData = _format.isCDataElement( tagName );
  +	state.unescaped = _format.isNonEscapingElement( tagName );
  +    }
  +
  +
  +    public void endElement( String tagName )
  +    {
  +	endElement( null, null, tagName );
  +    }
  +
  +
   
       //------------------------------------------//
       // Generic node serializing methods methods //
  @@ -475,7 +607,7 @@
   	if ( elem.hasChildNodes() ) {
   	    // Enter an element state, and serialize the children
   	    // one by one. Finally, end the element.
  -	    state = enterElementState( tagName, preserveSpace );
  +	    state = enterElementState( null, null, tagName, preserveSpace );
   	    state.doCData = _format.isCDataElement( tagName );
   	    state.unescaped = _format.isNonEscapingElement( tagName );
   	    child = elem.getFirstChild();