org.apache.cocoon.components.serializers.util.XHTMLSerializer Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.components.serializers.util;
import org.apache.cocoon.components.serializers.encoding.XHTMLEncoder;
import org.xml.sax.SAXException;
/**
* A pedantic XHTML serializer encoding all recognized entities with their
* proper HTML names.
*
* For configuration options of this serializer, please look at the
* {@link EncodingSerializer}, in addition to those, this serializer also
* support the specification of a default doctype. This default will be used
* if no document type is received in the SAX events, and can be configured
* in the following way:
*
*
* <serializer class="org.apache.cocoon.components.serializers..." ... >
* <doctype-default>mytype</doctype-default>
* </serializer>
*
*
* The value mytype can be one of:
*
*
* - "
none
"
* - Not to emit any document type declaration.
* - "
strict
"
* - The XHTML 1.0 Strict document type.
* - "
loose
"
* - The XHTML 1.0 Transitional document type.
* - "
frameset
"
* - The XHTML 1.0 Frameset document type.
*
*
* @version $Id: XHTMLSerializer.java 737005 2009-01-23 11:14:38Z andreas $
*/
public class XHTMLSerializer extends XMLSerializer {
/** The namespace URI for XHTML 1.0. */
public static final String XHTML1_NAMESPACE =
"http://www.w3.org/1999/xhtml";
/** A representation of the XHTML 1.0 strict document type. */
public static final DocType XHTML1_DOCTYPE_STRICT = new DocType(
"html", "-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
/** A representation of the XHTML 1.0 transitional document type. */
public static final DocType XHTML1_DOCTYPE_TRANSITIONAL = new DocType(
"html", "-//W3C//DTD XHTML 1.0 Transitional//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
/** A representation of the XHTML 1.0 frameset document type. */
public static final DocType XHTML1_DOCTYPE_FRAMESET = new DocType(
"html", "-//W3C//DTD XHTML 1.0 Frameset//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd");
/* ====================================================================== */
private static final XHTMLEncoder XHTML_ENCODER = new XHTMLEncoder();
protected boolean encodeCharacters = true;
/* ====================================================================== */
/** The DocType
instance representing the document. */
protected DocType doctype_default = null;
/** Define whether to put XML declaration in the head of the document. */
private String omitXmlDeclaration = null;
/* ====================================================================== */
/**
* Create a new instance of this XHTMLSerializer
*/
public XHTMLSerializer() {
super(XHTML_ENCODER);
}
/**
* Create a new instance of this XHTMLSerializer
*/
protected XHTMLSerializer(XHTMLEncoder encoder) {
super(encoder);
}
/**
* Return the MIME Content-Type produced by this serializer.
*/
public String getMimeType() {
if (this.charset == null) return("text/html");
return("text/html; charset=" + this.charset.getName());
}
public void setDoctypeDefault(String doctype) {
if ("none".equalsIgnoreCase(doctype)) {
this.doctype_default = null;
} else if ("strict".equalsIgnoreCase(doctype)) {
this.doctype_default = XHTML1_DOCTYPE_STRICT;
} else if ("loose".equalsIgnoreCase(doctype)) {
this.doctype_default = XHTML1_DOCTYPE_TRANSITIONAL;
} else if ("frameset".equalsIgnoreCase(doctype)) {
this.doctype_default = XHTML1_DOCTYPE_FRAMESET;
} else {
/* Default is transitional */
this.doctype_default = XHTML1_DOCTYPE_TRANSITIONAL;
}
}
public void setOmitXmlDeclaration(String value) {
this.omitXmlDeclaration = value;
}
/* ====================================================================== */
/**
* Write the XML document header.
*
* This method will write out the <?xml version="1.0"
* ...>
header unless omit-xml-declaration is set.
*
*/
protected void head()
throws SAXException {
if (!"yes".equals(this.omitXmlDeclaration)) {
super.head();
}
}
/**
* Receive notification of the beginning of the document body.
*
* @param uri The namespace URI of the root element.
* @param local The local name of the root element.
* @param qual The fully-qualified name of the root element.
*/
public void body(String uri, String local, String qual)
throws SAXException {
if (this.doctype == null) this.doctype = this.doctype_default;
if (this.namespaces.getUri("").length() == 0) {
this.namespaces.push("", XHTML1_NAMESPACE);
}
super.body(uri, local, qual);
}
/**
* Receive notification of the beginning of an element.
*
* @param uri The namespace URI of the root element.
* @param local The local name of the root element.
* @param qual The fully-qualified name of the root element.
* @param namespaces An array of String
objects containing
* the namespaces to be declared by this element.
* @param attributes An array of String
objects containing
* all attributes of this element.
*/
public void startElementImpl(String uri, String local, String qual,
String namespaces[][], String attributes[][])
throws SAXException {
if (uri.length() == 0) uri = XHTML1_NAMESPACE;
if (isCdataElement(local)) {
this.encodeCharacters = false;
}
super.startElementImpl(uri, local, qual, namespaces, attributes);
}
/**
* Receive notification of the end of an element.
*
* @param uri The namespace URI of the root element.
* @param local The local name of the root element.
* @param qual The fully-qualified name of the root element.
*/
public void endElementImpl(String uri, String local, String qual)
throws SAXException {
if (uri.length() == 0) uri = XHTML1_NAMESPACE;
if (XHTML1_NAMESPACE.equals(uri)) {
if ((local.equalsIgnoreCase("textarea")) ||
(local.equalsIgnoreCase("script")) ||
(local.equalsIgnoreCase("style"))) {
this.closeElement(false);
} else if (local.equalsIgnoreCase("head")) {
String loc = "meta";
String qua = namespaces.qualify(XHTML1_NAMESPACE, loc, "meta");
String nsp[][] = new String[0][0];
String att[][] = new String[2][ATTRIBUTE_LENGTH];
att[0][ATTRIBUTE_NSURI] = att[1][ATTRIBUTE_NSURI] = "";
att[0][ATTRIBUTE_LOCAL] = att[0][ATTRIBUTE_QNAME] = "http-equiv";
att[1][ATTRIBUTE_LOCAL] = att[1][ATTRIBUTE_QNAME] = "content";
att[0][ATTRIBUTE_VALUE] = "Content-Type";
att[1][ATTRIBUTE_VALUE] = this.getMimeType();
this.closeElement(false);
this.startElementImpl(XHTML1_NAMESPACE, loc, qua, nsp, att);
this.endElementImpl(XHTML1_NAMESPACE, loc, qua);
}
}
if (isCdataElement(local)) {
this.encodeCharacters = true;
}
super.endElementImpl(uri, local, qual);
}
/**
* script and style are CDATA sections by default, so no encoding
* @param localName The local name of the element.
* @return If the element should be serialized without encoding.
*/
protected boolean isCdataElement(String localName) {
String upperCase = localName.toUpperCase();
return "SCRIPT".equals(upperCase) || "STYLE".equals(upperCase);
}
/**
* Encode and write a specific part of an array of characters.
*/
protected void encode(char data[], int start, int length)
throws SAXException {
if (this.encodeCharacters) {
super.encode(data, start, length);
} else {
this.write(data, start, length);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy