diff --git a/jvm/src/test/scala/scala/xml/XMLTest.scala b/jvm/src/test/scala/scala/xml/XMLTest.scala
index 90e4a65c..d5a606d4 100644
--- a/jvm/src/test/scala/scala/xml/XMLTest.scala
+++ b/jvm/src/test/scala/scala/xml/XMLTest.scala
@@ -24,10 +24,10 @@ class XMLTestJVM {
def Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*): Elem =
scala.xml.Elem.apply(prefix, label, attributes, scope, minimizeEmpty = true, child: _*)
- lazy val parsedxml1: Elem = XML.load(new InputSource(new StringReader("")))
- lazy val parsedxml11: Elem = XML.load(new InputSource(new StringReader("")))
+ lazy val parsedxml1: Elem = XML.loadString("")
+ lazy val parsedxml11: Elem = XML.loadString("")
val xmlFile2: String = "Peter BunemanDan SuciuData on ze webJohn MitchellFoundations of Programming Languages"
- lazy val parsedxml2: Elem = XML.load(new InputSource(new StringReader(xmlFile2)))
+ lazy val parsedxml2: Elem = XML.loadString(xmlFile2)
@UnitTest
def equality(): Unit = {
@@ -46,9 +46,7 @@ class XMLTestJVM {
assertTrue(Array(parsedxml1).toList sameElements List(parsedxml11))
val x2: String = "Peter BunemanDan SuciuData on ze web"
-
- val i: InputSource = new InputSource(new StringReader(x2))
- val x2p: Elem = XML.load(i)
+ val x2p: Elem = XML.loadString(x2)
assertEquals(Elem(null, "book", e, sc,
Elem(null, "author", e, sc, Text("Peter Buneman")),
@@ -146,8 +144,7 @@ class XMLTestJVM {
val xmlAttrValueNorm: String = ""
{
- val isrcA: InputSource = new InputSource(new StringReader(xmlAttrValueNorm))
- val parsedxmlA: Elem = XML.load(isrcA)
+ val parsedxmlA: Elem = XML.loadString(xmlAttrValueNorm)
val c: Char = (parsedxmlA \ "@nom").text.charAt(0)
assertTrue(c == '\u015e')
}
@@ -689,6 +686,17 @@ class XMLTestJVM {
assertTrue(gotAnError)
}
+ // Here we see that opening InputStream prematurely, as was done previously, breaks XInclude.
+ @UnitTest(expected = classOf[org.xml.sax.SAXParseException]) def xIncludeNeedsSystemId(): Unit = {
+ val parserFactory = xercesInternal
+ parserFactory.setNamespaceAware(true)
+ parserFactory.setXIncludeAware(true)
+ XML
+ .withSAXParser(parserFactory.newSAXParser)
+ .load(getClass.getResource("site.xml").openStream())
+ .toString
+ }
+
// Now that we can use XML parser configured to be namespace-aware,
// we can also configure it to be XInclude-aware and process XML Includes:
def check(
@@ -700,7 +708,7 @@ class XMLTestJVM {
parserFactory.setXIncludeAware(true)
val actual: String = XML
.withSAXParser(parserFactory.newSAXParser)
- .load(getClass.getResource(resourceName).toString)
+ .load(getClass.getResource(resourceName))
.toString
assertEquals(expected, actual)
diff --git a/shared/src/main/scala/scala/xml/XML.scala b/shared/src/main/scala/scala/xml/XML.scala
index b5ea9133..16a23aa0 100755
--- a/shared/src/main/scala/scala/xml/XML.scala
+++ b/shared/src/main/scala/scala/xml/XML.scala
@@ -19,13 +19,13 @@ import java.nio.channels.Channels
import scala.util.control.Exception.ultimately
object Source {
- def fromFile(file: File): InputSource = new InputSource(new FileInputStream(file))
- def fromFile(fd: FileDescriptor): InputSource = new InputSource(new FileInputStream(fd))
- def fromFile(name: String): InputSource = new InputSource(new FileInputStream(name))
-
+ def fromFile(name: String): InputSource = fromFile(new File(name))
+ def fromFile(file: File): InputSource = fromUrl(file.toURI.toURL)
+ def fromUrl(url: java.net.URL): InputSource = fromSysId(url.toString)
+ def fromSysId(sysID: String): InputSource = new InputSource(sysID)
+ def fromFile(fd: FileDescriptor): InputSource = fromInputStream(new FileInputStream(fd))
def fromInputStream(is: InputStream): InputSource = new InputSource(is)
def fromReader(reader: Reader): InputSource = new InputSource(reader)
- def fromSysId(sysID: String): InputSource = new InputSource(sysID)
def fromString(string: String): InputSource = fromReader(new StringReader(string))
}
diff --git a/shared/src/main/scala/scala/xml/factory/XMLLoader.scala b/shared/src/main/scala/scala/xml/factory/XMLLoader.scala
index ff722d6e..acaf6353 100644
--- a/shared/src/main/scala/scala/xml/factory/XMLLoader.scala
+++ b/shared/src/main/scala/scala/xml/factory/XMLLoader.scala
@@ -14,7 +14,7 @@ package scala
package xml
package factory
-import org.xml.sax.{SAXNotRecognizedException, XMLReader}
+import org.xml.sax.{SAXNotRecognizedException, SAXNotSupportedException, XMLReader}
import javax.xml.parsers.SAXParserFactory
import parsing.{FactoryAdapter, NoBindingFactoryAdapter}
import java.io.{File, FileDescriptor, InputStream, Reader}
@@ -22,24 +22,28 @@ import java.net.URL
/**
* Presents collection of XML loading methods which use the parser
- * created by "def parser".
+ * created by "def parser" or the reader created by "def reader".
*/
trait XMLLoader[T <: Node] {
import scala.xml.Source._
def adapter: FactoryAdapter = new NoBindingFactoryAdapter()
+ private def setSafeDefaults(parserFactory: SAXParserFactory): Unit = {
+ parserFactory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true)
+ parserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
+ parserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
+ parserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
+ parserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false)
+ parserFactory.setFeature("http://xml.org/sax/features/resolve-dtd-uris", false)
+ parserFactory.setXIncludeAware(false)
+ parserFactory.setNamespaceAware(false)
+ }
+
private lazy val parserInstance: ThreadLocal[SAXParser] = new ThreadLocal[SAXParser] {
override def initialValue: SAXParser = {
- val parser: SAXParserFactory = SAXParserFactory.newInstance
- parser.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true)
- parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
- parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
- parser.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
- parser.setFeature("http://xml.org/sax/features/external-general-entities", false)
- parser.setFeature("http://xml.org/sax/features/resolve-dtd-uris", false)
- parser.setXIncludeAware(false)
- parser.setNamespaceAware(false)
- parser.newSAXParser
+ val parserFactory: SAXParserFactory = SAXParserFactory.newInstance
+ setSafeDefaults(parserFactory)
+ parserFactory.newSAXParser
}
}
@@ -51,72 +55,68 @@ trait XMLLoader[T <: Node] {
/**
* Loads XML from the given InputSource, using the supplied parser.
- * The methods available in scala.xml.XML use the XML parser in the JDK.
+ * The methods available in scala.xml.XML use the XML parser in the JDK
+ * (unless another parser is present on the classpath).
*/
- def loadXML(source: InputSource, parser: SAXParser): T = loadXML(source, parser.getXMLReader)
+ def loadXML(inputSource: InputSource, parser: SAXParser): T = loadXML(inputSource, parser.getXMLReader)
- def loadXMLNodes(source: InputSource, parser: SAXParser): Seq[Node] = loadXMLNodes(source, parser.getXMLReader)
+ def loadXMLNodes(inputSource: InputSource, parser: SAXParser): Seq[Node] = loadXMLNodes(inputSource, parser.getXMLReader)
- private def loadXML(source: InputSource, reader: XMLReader): T = {
- val result: FactoryAdapter = parse(source, reader)
+ private def loadXML(inputSource: InputSource, reader: XMLReader): T = {
+ val result: FactoryAdapter = parse(inputSource, reader)
result.rootElem.asInstanceOf[T]
}
-
- private def loadXMLNodes(source: InputSource, reader: XMLReader): Seq[Node] = {
- val result: FactoryAdapter = parse(source, reader)
+
+ private def loadXMLNodes(inputSource: InputSource, reader: XMLReader): Seq[Node] = {
+ val result: FactoryAdapter = parse(inputSource, reader)
result.prolog ++ (result.rootElem :: result.epilogue)
}
- private def parse(source: InputSource, reader: XMLReader): FactoryAdapter = {
- if (source == null) throw new IllegalArgumentException("InputSource cannot be null")
+ private def parse(inputSource: InputSource, xmlReader: XMLReader): FactoryAdapter = {
+ if (inputSource == null) throw new IllegalArgumentException("InputSource cannot be null")
val result: FactoryAdapter = adapter
- reader.setContentHandler(result)
- reader.setDTDHandler(result)
+ xmlReader.setContentHandler(result)
+ xmlReader.setDTDHandler(result)
/* Do not overwrite pre-configured EntityResolver. */
- if (reader.getEntityResolver == null) reader.setEntityResolver(result)
+ if (xmlReader.getEntityResolver == null) xmlReader.setEntityResolver(result)
/* Do not overwrite pre-configured ErrorHandler. */
- if (reader.getErrorHandler == null) reader.setErrorHandler(result)
+ if (xmlReader.getErrorHandler == null) xmlReader.setErrorHandler(result)
try {
- reader.setProperty("http://xml.org/sax/properties/lexical-handler", result)
+ xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", result)
} catch {
case _: SAXNotRecognizedException =>
+ case _: SAXNotSupportedException =>
}
result.scopeStack = TopScope :: result.scopeStack
- reader.parse(source)
+ xmlReader.parse(inputSource)
result.scopeStack = result.scopeStack.tail
result
}
- /** loads XML from given InputSource. */
- def load(source: InputSource): T = loadXML(source, reader)
-
- /** Loads XML from the given file, file descriptor, or filename. */
+ /** Loads XML. */
+ def load(inputSource: InputSource): T = loadXML(inputSource, reader)
+ def loadFile(fileName: String): T = load(fromFile(fileName))
def loadFile(file: File): T = load(fromFile(file))
- def loadFile(fd: FileDescriptor): T = load(fromFile(fd))
- def loadFile(name: String): T = load(fromFile(name))
-
- /** loads XML from given InputStream, Reader, sysID, or URL. */
- def load(is: InputStream): T = load(fromInputStream(is))
+ def load(url: URL): T = load(fromUrl(url))
+ def load(sysId: String): T = load(fromSysId(sysId))
+ def loadFile(fileDescriptor: FileDescriptor): T = load(fromFile(fileDescriptor))
+ def load(inputStream: InputStream): T = load(fromInputStream(inputStream))
def load(reader: Reader): T = load(fromReader(reader))
- def load(sysID: String): T = load(fromSysId(sysID))
- def load(url: URL): T = load(fromInputStream(url.openStream()))
-
- /** Loads XML from the given String. */
def loadString(string: String): T = load(fromString(string))
/** Load XML nodes, including comments and processing instructions that precede and follow the root element. */
- def loadNodes(source: InputSource): Seq[Node] = loadXMLNodes(source, reader)
+ def loadNodes(inputSource: InputSource): Seq[Node] = loadXMLNodes(inputSource, reader)
+ def loadFileNodes(fileName: String): Seq[Node] = loadNodes(fromFile(fileName))
def loadFileNodes(file: File): Seq[Node] = loadNodes(fromFile(file))
- def loadFileNodes(fd: FileDescriptor): Seq[Node] = loadNodes(fromFile(fd))
- def loadFileNodes(name: String): Seq[Node] = loadNodes(fromFile(name))
- def loadNodes(is: InputStream): Seq[Node] = loadNodes(fromInputStream(is))
+ def loadNodes(url: URL): Seq[Node] = loadNodes(fromUrl(url))
+ def loadNodes(sysId: String): Seq[Node] = loadNodes(fromSysId(sysId))
+ def loadFileNodes(fileDescriptor: FileDescriptor): Seq[Node] = loadNodes(fromFile(fileDescriptor))
+ def loadNodes(inputStream: InputStream): Seq[Node] = loadNodes(fromInputStream(inputStream))
def loadNodes(reader: Reader): Seq[Node] = loadNodes(fromReader(reader))
- def loadNodes(sysID: String): Seq[Node] = loadNodes(fromSysId(sysID))
- def loadNodes(url: URL): Seq[Node] = loadNodes(fromInputStream(url.openStream()))
def loadStringNodes(string: String): Seq[Node] = loadNodes(fromString(string))
}