Skip to content

Commit 6e10bf0

Browse files
committed
Allow using FactoryAdapter as ContentHandler
1 parent 5b89505 commit 6e10bf0

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

jvm/src/test/scala/scala/xml/XMLTest.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package scala.xml
22

33
import org.junit.{Test => UnitTest}
44
import org.junit.Assert.{assertEquals, assertFalse, assertNull, assertThrows, assertTrue}
5-
import java.io.{ByteArrayInputStream, ByteArrayOutputStream, InputStreamReader, IOException, ObjectInputStream,
6-
ObjectOutputStream, OutputStreamWriter, PrintStream, StringWriter}
5+
6+
import java.io.{ByteArrayInputStream, ByteArrayOutputStream, IOException, InputStream, InputStreamReader, ObjectInputStream, ObjectOutputStream, OutputStreamWriter, PrintStream, StringWriter}
77
import java.net.URL
88
import scala.xml.dtd.{DocType, PublicID}
99
import scala.xml.parsing.ConstructingParser
@@ -1081,4 +1081,15 @@ class XMLTestJVM {
10811081

10821082
assertEquals("", x.xEntityValue())
10831083
}
1084+
1085+
@UnitTest
1086+
def factoryAdapterAsContentHandler(): Unit = {
1087+
// scala-xml#764
1088+
val p = defaultParserFactory.newSAXParser()
1089+
val handler = new parsing.NoBindingFactoryAdapter
1090+
val input = new ByteArrayInputStream("<hello>world</hello>".getBytes("UTF-8"))
1091+
p.parse(input, handler)
1092+
val n: Node = handler.document.docElem
1093+
assert(n.text == "world")
1094+
}
10841095
}

shared/src/main/scala/scala/xml/parsing/FactoryAdapter.scala

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,47 @@ abstract class FactoryAdapter extends DefaultHandler2 with factory.XMLLoader[Nod
4343
// reference to the XMLReader that parses the document; this is used to query
4444
// features (e.g., 'is-standalone') and properties (e.g., document-xml-version) -
4545
// see http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html
46-
private var xmlReader: Option[XMLReader] = None
46+
private[this] var xmlReader: Option[XMLReader] = None
4747

48-
private var dtdBuilder: Option[DtdBuilder] = None
48+
private[this] var dtdBuilder: Option[DtdBuilder] = None
4949
private def inDtd: Boolean = dtdBuilder.isDefined && !dtdBuilder.get.isDone
5050

51-
private var document: Option[Document] = None
52-
private var baseURI: Option[String] = None
53-
private var xmlEncoding: Option[String] = None
5451

55-
private var prefixMappings: List[(String, String)] = List.empty
52+
/**
53+
* The [[Document]] built during [[endDocument]]. This allows using [[FactoryAdapter]] (or [[NoBindingFactoryAdapter]])
54+
* for converting other XML representations accepting an [[org.xml.sax.ContentHandler]] to scala.xml.
55+
*
56+
* {{{
57+
* // using org.jdom:jdom2:2.0.6.1
58+
*
59+
* import scala.xml._
60+
* import org.jdom2._
61+
* import org.jdom2.output._
62+
*
63+
* def jd2s(d: Document): Node = {
64+
* val out = new SAXOutputter
65+
* val h = new parsing.NoBindingFactoryAdapter
66+
* out.setContentHandler(h)
67+
* out.output(d)
68+
* h.document.docElem
69+
* }
70+
* }}}
71+
*/
72+
def document: Document = _document
73+
74+
private[this] var _document: Document = null
75+
private[this] var baseURI: Option[String] = None
76+
private[this] var xmlEncoding: Option[String] = None
77+
78+
private[this] var prefixMappings: List[(String, String)] = List.empty
5679

5780
// TODO all the variables should be private, but - binary compatibility...
5881
var prolog: List[Node] = List.empty
5982
var rootElem: Node = _
6083
var epilogue: List[Node] = List.empty
6184

6285
val buffer: StringBuilder = new StringBuilder()
63-
private var inCDATA: Boolean = false
86+
private[this] var inCDATA: Boolean = false
6487

6588
/** List of attributes
6689
*
@@ -140,7 +163,7 @@ abstract class FactoryAdapter extends DefaultHandler2 with factory.XMLLoader[Nod
140163
this.xmlReader = Some(xmlReader)
141164
xmlReader.parse(inputSource)
142165

143-
document.get
166+
_document
144167
}
145168

146169
// abstract methods
@@ -213,7 +236,7 @@ abstract class FactoryAdapter extends DefaultHandler2 with factory.XMLLoader[Nod
213236
epilogue = hStack.init.reverse
214237

215238
val document = new Document
216-
this.document = Some(document)
239+
this._document = document
217240
document.children = prolog ++ rootElem ++ epilogue
218241
document.docElem = rootElem
219242
document.dtd = dtdBuilder.map(_.dtd).orNull
@@ -222,15 +245,15 @@ abstract class FactoryAdapter extends DefaultHandler2 with factory.XMLLoader[Nod
222245

223246
document.version =
224247
try {
225-
Option(xmlReader.get.getProperty("http://xml.org/sax/properties/document-xml-version").asInstanceOf[String])
248+
xmlReader.map(_.getProperty("http://xml.org/sax/properties/document-xml-version").asInstanceOf[String])
226249
} catch {
227250
case _: SAXNotRecognizedException => None
228251
case _: SAXNotSupportedException => None
229252
}
230253

231254
document.standAlone =
232255
try {
233-
Some(xmlReader.get.getFeature("http://xml.org/sax/features/is-standalone"))
256+
xmlReader.map(_.getFeature("http://xml.org/sax/features/is-standalone"))
234257
} catch {
235258
case _: SAXNotRecognizedException => None
236259
case _: SAXNotSupportedException => None

0 commit comments

Comments
 (0)