package scala.xml
package parsing
import java.io.{ InputStream, Reader, File, FileDescriptor, FileInputStream }
import scala.collection.{ mutable, Iterator }
import org.xml.sax.Attributes
import org.xml.sax.helpers.DefaultHandler
trait ConsoleErrorHandler extends DefaultHandler {
override def warning(ex: SAXParseException): Unit = { }
override def error(ex: SAXParseException): Unit = printError("Error", ex)
override def fatalError(ex: SAXParseException): Unit = printError("Fatal Error", ex)
protected def printError(errtype: String, ex: SAXParseException): Unit =
Console.withOut(Console.err) {
val s = "[%s]:%d:%d: %s".format(
errtype, ex.getLineNumber, ex.getColumnNumber, ex.getMessage)
Console.println(s)
Console.flush
}
}
abstract class FactoryAdapter extends DefaultHandler with factory.XMLLoader[Node] {
var rootElem: Node = null
val buffer = new StringBuilder()
val attribStack = new mutable.Stack[MetaData]
val hStack = new mutable.Stack[Node]
val tagStack = new mutable.Stack[String]
var scopeStack = new mutable.Stack[NamespaceBinding]
var curTag : String = null
var capture: Boolean = false
def nodeContainsText(localName: String): Boolean
def createNode(pre: String, elemName: String, attribs: MetaData,
scope: NamespaceBinding, chIter: List[Node]): Node
def createText(text: String): Text
def createProcInstr(target: String, data: String): Seq[ProcInstr]
val normalizeWhitespace = false
override def characters(ch: Array[Char], offset: Int, length: Int): Unit = {
if (!capture) return
else if (!normalizeWhitespace) buffer.appendAll(ch, offset, length)
else {
var it = ch.slice(offset, offset + length).iterator
while (it.hasNext) {
val c = it.next
val isSpace = c.isWhitespace
buffer append (if (isSpace) ' ' else c)
if (isSpace)
it = it dropWhile (_.isWhitespace)
}
}
}
private def splitName(s: String) = {
val idx = s indexOf ':'
if (idx < 0) (null, s)
else (s take idx, s drop (idx + 1))
}
override def startElement(
uri: String,
_localName: String,
qname: String,
attributes: Attributes): Unit =
{
captureText()
tagStack push curTag
curTag = qname
val localName = splitName(qname)._2
capture = nodeContainsText(localName)
hStack push null
var m: MetaData = Null
var scpe: NamespaceBinding =
if (scopeStack.isEmpty) TopScope
else scopeStack.top
for (i <- 0 until attributes.getLength()) {
val qname = attributes getQName i
val value = attributes getValue i
val (pre, key) = splitName(qname)
def nullIfEmpty(s: String) = if (s == "") null else s
if (pre == "xmlns" || (pre == null && qname == "xmlns")) {
val arg = if (pre == null) null else key
scpe = new NamespaceBinding(arg, nullIfEmpty(value), scpe)
}
else
m = Attribute(Option(pre), key, Text(value), m)
}
scopeStack push scpe
attribStack push m
}
def captureText(): Unit = {
if (capture && buffer.length > 0)
hStack push createText(buffer.toString)
buffer.clear()
}
override def endElement(uri: String , _localName: String, qname: String): Unit = {
captureText()
val metaData = attribStack.pop
val v = (Iterator continually hStack.pop takeWhile (_ != null)).toList.reverse
val (pre, localName) = splitName(qname)
val scp = scopeStack.pop
rootElem = createNode(pre, localName, metaData, scp, v)
hStack push rootElem
curTag = tagStack.pop
capture = curTag != null && nodeContainsText(curTag)
}
override def processingInstruction(target: String, data: String) {
hStack pushAll createProcInstr(target, data)
}
}
<iframe src="https://xuwei-k.github.io/scala-library-sxr/scala-library-2.9.1/scala/xml/parsing/FactoryAdapter.scala.html" width="1280" height="720" frameborder="0"> </iframe>