From 61a2691875c518e3564c3552fa004b4df730b810 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Fri, 21 Sep 2018 10:08:06 -0400 Subject: [PATCH] Fix exception in XhtmlParser with HTML5 docype Make characters, including whitespace, after the `html' identifier in be optional. Otherwise, the following errors are emitted: file.xml:2:15: whitespace expected ^ file.xml:2:15: document must contain exactly one element And a java.lang.NullPointerException is thrown. Unfortunately, testing with Source.fromString doesn't reproduce the NullPointerException that occurs with Source.fromFile. --- .../xml/parsing/ConstructingParserTest.scala | 52 ++++++++++++++++ .../scala/xml/parsing/XhtmlParserTest.scala | 61 +++++++++++++++++++ .../scala/xml/parsing/MarkupParser.scala | 2 +- 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 jvm/src/test/scala/scala/xml/parsing/XhtmlParserTest.scala diff --git a/jvm/src/test/scala/scala/xml/parsing/ConstructingParserTest.scala b/jvm/src/test/scala/scala/xml/parsing/ConstructingParserTest.scala index d67524c51..4a8cf3134 100644 --- a/jvm/src/test/scala/scala/xml/parsing/ConstructingParserTest.scala +++ b/jvm/src/test/scala/scala/xml/parsing/ConstructingParserTest.scala @@ -4,6 +4,7 @@ package parsing import scala.io.Source import org.junit.Test import scala.xml.JUnitAssertsForXML.{ assertEquals => assertXml } +import org.junit.Assert.assertEquals class ConstructingParserTest { @@ -19,4 +20,55 @@ class ConstructingParserTest { } + /* Example of using SYSTEM in DOCTYPE */ + @Test + def docbookTest = { + val xml = + """| + | + | Book + | + | Chapter + | Text + | + |""".stripMargin + + val expected = + Book + + Chapter + Text + + + + val source = new Source { + val iter = xml.iterator + override def reportError(pos: Int, msg: String, out: java.io.PrintStream = Console.err) = {} + } + + val doc = ConstructingParser.fromSource(source, true).document + + assertEquals(expected, doc.theSeq) + } + + /* Unsupported use of lowercase DOCTYPE and SYSTEM */ + @Test(expected = classOf[scala.xml.parsing.FatalError]) + def docbookFail: Unit = { + val xml = + """| + | + |Book + | + |Chapter + |Text + | + |""".stripMargin + + val source = new Source { + val iter = xml.iterator + override def reportError(pos: Int, msg: String, out: java.io.PrintStream = Console.err) = {} + } + + ConstructingParser.fromSource(source, true).content(TopScope) + } } diff --git a/jvm/src/test/scala/scala/xml/parsing/XhtmlParserTest.scala b/jvm/src/test/scala/scala/xml/parsing/XhtmlParserTest.scala new file mode 100644 index 000000000..fd7c8ccae --- /dev/null +++ b/jvm/src/test/scala/scala/xml/parsing/XhtmlParserTest.scala @@ -0,0 +1,61 @@ +package scala.xml +package parsing + +import scala.io.Source + +import org.junit.Test +import org.junit.Assert.assertEquals + +class XhtmlParserTest { + + @Test + def issue259: Unit = { + val xml = + """| + | + | + | + | + | + |

Text

+ | + |""".stripMargin + + val expected = + + + + +

Text

+ + + + assertEquals(expected, XhtmlParser(Source.fromString(xml)).theSeq) + } + + @Test + def html4Strict: Unit = { + val xml = + """| + | + | + | Title + | + | + |

Text

+ | + |""".stripMargin + + val expected = + + Title + + +

Text

+ + + + assertEquals(expected, XhtmlParser(Source.fromString(xml)).theSeq) + } +} diff --git a/shared/src/main/scala/scala/xml/parsing/MarkupParser.scala b/shared/src/main/scala/scala/xml/parsing/MarkupParser.scala index 0b2f0d567..880d9bd7b 100755 --- a/shared/src/main/scala/scala/xml/parsing/MarkupParser.scala +++ b/shared/src/main/scala/scala/xml/parsing/MarkupParser.scala @@ -518,7 +518,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests { xToken("DOCTYPE") xSpace() val n = xName - xSpace() + xSpaceOpt() //external ID if ('S' == ch || 'P' == ch) { extID = externalID()