org.codehaus.stax2.ri.Stax2WriterImpl Maven / Gradle / Ivy
Go to download
Stax2 API is an extension to basic Stax 1.0 API that adds significant new functionality, such as full-featured bi-direction validation interface and high-performance Typed Access API.
/* Stax2 API extension for Streaming Api for Xml processing (StAX).
*
* Copyright (c) 2006- Tatu Saloranta, [email protected]
*
* Licensed under the License specified in file LICENSE, included with
* the source code.
* You may not use this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.stax2.ri;
import javax.xml.stream.*;
import org.codehaus.stax2.*;
import org.codehaus.stax2.validation.*;
/**
* This is a partial base implementation of {@link XMLStreamWriter2},
* the extended stream writer that is part of Stax2.
*/
public abstract class Stax2WriterImpl
implements XMLStreamWriter2 /* From Stax2 */
,XMLStreamConstants
{
/*
///////////////////////////////////////////////////////////
// Life-cycle methods
///////////////////////////////////////////////////////////
*/
protected Stax2WriterImpl() { }
/*
///////////////////////////////////////////////////////////
// XMLStreamWriter2 (StAX2) implementation
///////////////////////////////////////////////////////////
*/
public boolean isPropertySupported(String name)
{
/* No base properties (or should we have something for impl
* name, version?)
*/
return false;
}
public boolean setProperty(String name, Object value)
{
throw new IllegalArgumentException("No settable property '"+name+"'");
}
public abstract XMLStreamLocation2 getLocation();
public abstract String getEncoding();
public void writeCData(char[] text, int start, int len)
throws XMLStreamException
{
writeCData(new String(text, start, len));
}
public void writeDTD(String rootName, String systemId, String publicId,
String internalSubset)
throws XMLStreamException
{
/* This may or may not work... depending on how well underlying
* implementation follows stax 1.0 spec (it should work)
*/
StringBuffer sb = new StringBuffer();
sb.append(" 0) {
sb.append(" [");
sb.append(internalSubset);
sb.append(']');
}
sb.append('>');
writeDTD(sb.toString());
}
public void writeFullEndElement()
throws XMLStreamException
{
/* This should work with base Stax 1.0 implementations.
* Sub-classes are, however, encouraged to implement it
* more directly, if possible.
*/
writeCharacters("");
writeEndElement();
}
public void writeSpace(String text)
throws XMLStreamException
{
/* Hmmh. Two choices: either try to write as regular characters,
* or output as is via raw calls. Latter would be safer, if we
* had access to it; former may escape incorrectly.
* While this may not be optimal, let's try former
*/
writeRaw(text);
}
public void writeSpace(char[] text, int offset, int length)
throws XMLStreamException
{
// See comments above...
writeRaw(text, offset, length);
}
public abstract void writeStartDocument(String version, String encoding,
boolean standAlone)
throws XMLStreamException;
/*
///////////////////////////////////////////////////////////
// Stax2, Pass-through methods
///////////////////////////////////////////////////////////
*/
public void writeRaw(String text)
throws XMLStreamException
{
writeRaw(text, 0, text.length());
}
public abstract void writeRaw(String text, int offset, int len)
throws XMLStreamException;
public abstract void writeRaw(char[] text, int offset, int length)
throws XMLStreamException;
public void copyEventFromReader(XMLStreamReader2 sr, boolean preserveEventData)
throws XMLStreamException
{
switch (sr.getEventType()) {
case START_DOCUMENT:
{
String version = sr.getVersion();
/* No real declaration? If so, we don't want to output
* anything, to replicate as closely as possible the
* source document
*/
if (version == null || version.length() == 0) {
; // no output if no real input
} else {
if (sr.standaloneSet()) {
writeStartDocument(sr.getVersion(),
sr.getCharacterEncodingScheme(),
sr.isStandalone());
} else {
writeStartDocument(sr.getCharacterEncodingScheme(),
sr.getVersion());
}
}
}
return;
case END_DOCUMENT:
writeEndDocument();
return;
// Element start/end events:
case START_ELEMENT:
/* Start element is bit trickier to output since there
* may be differences between repairing/non-repairing
* writers. But let's try a generic handling here.
*/
copyStartElement(sr);
return;
case END_ELEMENT:
writeEndElement();
return;
case SPACE:
writeSpace(sr.getTextCharacters(), sr.getTextStart(), sr.getTextLength());
return;
case CDATA:
writeCData(sr.getTextCharacters(), sr.getTextStart(), sr.getTextLength());
return;
case CHARACTERS:
writeCharacters(sr.getTextCharacters(), sr.getTextStart(), sr.getTextLength());
return;
case COMMENT:
writeComment(sr.getText());
return;
case PROCESSING_INSTRUCTION:
writeProcessingInstruction(sr.getPITarget(), sr.getPIData());
return;
case DTD:
{
DTDInfo info = sr.getDTDInfo();
if (info == null) {
/* Hmmmh. Can this happen for non-DTD-aware readers?
* And if so, what should we do?
*/
throw new XMLStreamException("Current state DOCTYPE, but not DTDInfo Object returned -- reader doesn't support DTDs?");
}
writeDTD(info.getDTDRootName(), info.getDTDSystemId(),
info.getDTDPublicId(), info.getDTDInternalSubset());
}
return;
case ENTITY_REFERENCE:
writeEntityRef(sr.getLocalName());
return;
case ATTRIBUTE:
case NAMESPACE:
case ENTITY_DECLARATION:
case NOTATION_DECLARATION:
// Let's just fall back to throw the exception
}
throw new XMLStreamException("Unrecognized event type ("
+sr.getEventType()+"); not sure how to copy");
}
/*
///////////////////////////////////////////////////////////
// Stax2, validation
///////////////////////////////////////////////////////////
*/
public XMLValidator validateAgainst(XMLValidationSchema schema)
throws XMLStreamException
{
throw new UnsupportedOperationException("Not yet implemented");
}
public XMLValidator stopValidatingAgainst(XMLValidationSchema schema)
throws XMLStreamException
{
return null;
}
public XMLValidator stopValidatingAgainst(XMLValidator validator)
throws XMLStreamException
{
return null;
}
public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h)
{
/* Not a real problem: although we can't do anything with it
* (without real validator integration)
*/
return null;
}
/*
///////////////////////////////////////////////////////////
// Helper methods
///////////////////////////////////////////////////////////
*/
/**
* Basic implementation of copy operation. It is likely that
* sub-classes can implement more efficient copy operations: if so,
* they should do so.
*/
protected void copyStartElement(XMLStreamReader sr)
throws XMLStreamException
{
// Any namespace declarations/bindings?
int nsCount = sr.getNamespaceCount();
if (nsCount > 0) { // yup, got some...
/* First, need to (or at least, should?) add prefix bindings:
* (may not be 100% required, but probably a good thing to do,
* just so that app code has access to prefixes then)
*/
for (int i = 0; i < nsCount; ++i) {
String prefix = sr.getNamespacePrefix(i);
String uri = sr.getNamespaceURI(i);
if (prefix == null || prefix.length() == 0) { // default NS
setDefaultNamespace(uri);
} else {
setPrefix(prefix, uri);
}
}
}
writeStartElement(sr.getPrefix(), sr.getLocalName(), sr.getNamespaceURI());
if (nsCount > 0) {
// And then output actual namespace declarations:
for (int i = 0; i < nsCount; ++i) {
String prefix = sr.getNamespacePrefix(i);
String uri = sr.getNamespaceURI(i);
if (prefix == null || prefix.length() == 0) { // default NS
writeDefaultNamespace(uri);
} else {
writeNamespace(prefix, uri);
}
}
}
/* And then let's just output attributes. But should we copy the
* implicit attributes (created via attribute defaulting?)
*/
int attrCount = sr.getAttributeCount();
if (attrCount > 0) {
for (int i = 0; i < attrCount; ++i) {
writeAttribute(sr.getAttributePrefix(i),
sr.getAttributeNamespace(i),
sr.getAttributeLocalName(i),
sr.getAttributeValue(i));
}
}
}
}