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();