scala.xml.include.sax.XIncluder.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-library Show documentation
Show all versions of scala-library Show documentation
Standard library for the Scala Programming Language
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.xml
package include.sax
import scala.xml.include._
import scala.collection.mutable
import org.xml.sax.{ ContentHandler, XMLReader, Locator, Attributes }
import org.xml.sax.ext.LexicalHandler
import java.io.{ File, OutputStream, OutputStreamWriter, Writer, IOException }
/** XIncluder is a SAX `ContentHandler` that writes its XML document onto
* an output stream after resolving all `xinclude:include` elements.
*
* Based on Eliotte Rusty Harold's SAXXIncluder.
*/
class XIncluder(outs: OutputStream, encoding: String) extends ContentHandler with LexicalHandler {
var out = new OutputStreamWriter(outs, encoding)
def setDocumentLocator(locator: Locator) {}
def startDocument() {
try {
out.write("\r\n");
}
catch {
case e:IOException =>
throw new SAXException("Write failed", e)
}
}
def endDocument() {
try {
out.flush()
}
catch {
case e:IOException =>
throw new SAXException("Flush failed", e)
}
}
def startPrefixMapping(prefix: String , uri: String) {}
def endPrefixMapping(prefix: String) {}
def startElement(namespaceURI: String, localName: String, qualifiedName: String, atts: Attributes) = {
try {
out.write("<" + qualifiedName);
var i = 0; while (i < atts.getLength()) {
out.write(" ");
out.write(atts.getQName(i));
out.write("='");
val value = atts.getValue(i);
// @todo Need to use character references if the encoding
// can't support the character
out.write(scala.xml.Utility.escape(value))
out.write("'");
i += 1
}
out.write(">")
}
catch {
case e:IOException =>
throw new SAXException("Write failed", e)
}
}
def endElement(namespaceURI: String, localName:String, qualifiedName: String) {
try {
out.write("" + qualifiedName + ">")
}
catch {
case e: IOException =>
throw new SAXException("Write failed", e)
}
}
// need to escape characters that are not in the given
// encoding using character references????
def characters(ch: Array[Char], start: Int, length: Int) {
try {
var i = 0; while (i < length) {
val c = ch(start+i);
if (c == '&') out.write("&");
else if (c == '<') out.write("<");
// This next fix is normally not necessary.
// However, it is required if text contains ]]>
// (The end CDATA section delimiter)
else if (c == '>') out.write(">");
else out.write(c);
i += 1
}
}
catch {
case e: IOException =>
throw new SAXException("Write failed", e);
}
}
def ignorableWhitespace(ch: Array[Char], start: Int , length: Int) {
this.characters(ch, start, length)
}
// do I need to escape text in PI????
def processingInstruction(target: String, data: String) {
try {
out.write("" + target + " " + data + "?>")
}
catch {
case e:IOException =>
throw new SAXException("Write failed", e)
}
}
def skippedEntity(name: String) {
try {
out.write("&" + name + ";")
}
catch {
case e:IOException =>
throw new SAXException("Write failed", e)
}
}
// LexicalHandler methods
private var inDTD: Boolean = false
private val entities = new mutable.Stack[String]()
def startDTD(name: String, publicID: String, systemID: String) {
inDTD = true
// if this is the source document, output a DOCTYPE declaration
if (entities.isEmpty) {
var id = ""
if (publicID != null) id = " PUBLIC \"" + publicID + "\" \"" + systemID + '"';
else if (systemID != null) id = " SYSTEM \"" + systemID + '"';
try {
out.write("\r\n")
}
catch {
case e:IOException =>
throw new SAXException("Error while writing DOCTYPE", e)
}
}
}
def endDTD() {}
def startEntity(name: String) {
entities push name
}
def endEntity(name: String) {
entities.pop()
}
def startCDATA() {}
def endCDATA() {}
// Just need this reference so we can ask if a comment is
// inside an include element or not
private var filter: XIncludeFilter = null
def setFilter(filter: XIncludeFilter) {
this.filter = filter
}
def comment(ch: Array[Char], start: Int, length: Int) {
if (!inDTD && !filter.insideIncludeElement()) {
try {
out.write("")
}
catch {
case e: IOException =>
throw new SAXException("Write failed", e)
}
}
}
}