From 890a7c509552fe97f8df00833c3d57d556ca6337 Mon Sep 17 00:00:00 2001 From: Burak Emir Date: Sat, 12 Apr 2008 01:58:00 +0000 Subject: made xml.pull functional --- src/library/scala/xml/pull/XMLEvent.scala | 20 ++++++++++++-- src/library/scala/xml/pull/XMLEventReader.scala | 35 +++++++++++++++++-------- test/files/jvm/xmlpull.scala | 31 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 test/files/jvm/xmlpull.scala diff --git a/src/library/scala/xml/pull/XMLEvent.scala b/src/library/scala/xml/pull/XMLEvent.scala index 622a3e7b87..65b8503eed 100644 --- a/src/library/scala/xml/pull/XMLEvent.scala +++ b/src/library/scala/xml/pull/XMLEvent.scala @@ -12,9 +12,25 @@ package scala.xml.pull /** This class represents an XML event for pull parsing. + * Pull parsing means that during the traversal of the XML + * tree we are parsing, each "event" is returned to the caller + * and the traversal is suspended. */ trait XMLEvent -case class ElemStart(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) extends XMLEvent +/** An element is encountered the first time */ +case class EvElemStart(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) extends XMLEvent -case class ElemEnd(pre: String, label: String) extends XMLEvent +/** An element is encountered the last time */ +case class EvElemEnd(pre: String, label: String) extends XMLEvent +/** A text node is encountered */ +case class EvText(text: String) extends XMLEvent + +/** An entity reference is encountered */ +case class EvEntityRef(entity: String) extends XMLEvent + +/** A processing instruction is encountered */ +case class EvProcInstr(target: String, text: String) extends XMLEvent + +/** A comment is encountered */ +case class EvComment(text: String) extends XMLEvent diff --git a/src/library/scala/xml/pull/XMLEventReader.scala b/src/library/scala/xml/pull/XMLEventReader.scala index bcc48af1e7..e17a9e0017 100644 --- a/src/library/scala/xml/pull/XMLEventReader.scala +++ b/src/library/scala/xml/pull/XMLEventReader.scala @@ -58,7 +58,7 @@ class XMLEventReader extends Iterator[XMLEvent] { wait() } continue = true - notifyAll + notify() } def getAndClearEvent: XMLEvent = synchronized { while (xmlEvent eq null) { @@ -72,10 +72,14 @@ class XMLEventReader extends Iterator[XMLEvent] { xmlEvent = e } - def doNotify() = synchronized { + def doNotify(): NodeSeq = synchronized { XMLEventReader.this.continue = false - notifyAll() - while (!XMLEventReader.this.continue) wait(); + notify() + while (!XMLEventReader.this.continue) { + try { wait() } catch { + case _: java.lang.InterruptedException => /* ignore */ + } + } NodeSeq.Empty } @@ -89,38 +93,47 @@ class XMLEventReader extends Iterator[XMLEvent] { def hasNext = true + // After calling stop, one must call initialize to be able to get new events. + def stop = { + continue = true; + parserThread.interrupt(); + parserThread = null; + } + var parserThread: Thread = null class Parser extends MarkupHandler with MarkupParser with ExternalSources with Runnable { val preserveWS = true val input = XMLEventReader.this.getSource + // document must contain one element - avoid spurious syntax error + final val ignore_node = override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) { - setEvent(ElemStart(pre, label, attrs, scope)); doNotify + setEvent(EvElemStart(pre, label, attrs, scope)); doNotify } override def elemEnd(pos: Int, pre: String, label: String) { - setEvent(ElemEnd(pre, label)); doNotify + setEvent(EvElemEnd(pre, label)); doNotify } final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = - NodeSeq.Empty + ignore_node def procInstr(pos: Int, target: String, txt: String): NodeSeq = { - setEvent(ElemStart(null, "comm", null, null)); doNotify + setEvent(EvProcInstr(target, txt)); doNotify } def comment(pos: Int, txt: String): NodeSeq = { - setEvent(ElemStart(null, "comm", null, null)); doNotify + setEvent(EvComment(txt)); doNotify } def entityRef(pos: Int, n: String): NodeSeq = { - setEvent(ElemStart(null, "eref", null, null)); doNotify + setEvent(EvEntityRef(n)); doNotify } def text(pos: Int, txt:String): NodeSeq = { - setEvent(ElemStart(null, "tex", null, null)); doNotify + setEvent(EvText(txt)); doNotify } override def run() { diff --git a/test/files/jvm/xmlpull.scala b/test/files/jvm/xmlpull.scala new file mode 100644 index 0000000000..1f0e6a8497 --- /dev/null +++ b/test/files/jvm/xmlpull.scala @@ -0,0 +1,31 @@ +import scala.xml._ +import scala.xml.pull._ +import scala.io.Source + +object Test { + + val src = Source.fromString("!") + + def main(args: Array[String]) { + var er = new XMLEventReader().initialize(src) + er.next match { + case EvElemStart(_, "hello", _, _) => //println("1") + } + er.next match { + case EvElemStart(_, "world", _, _) => //println("2") + } + er.next match { + case EvElemEnd(_, "world") => //println("3") + } + er.next match { + case EvText("!") => //println("4") + } + er.next match { + case EvElemEnd(_, "hello") => //println("5") + } + // you get the picture... + er.stop // allow thread to be garbage-collected + //println("6") + } +} + -- cgit v1.2.3