From 143fe4315784a0bc4675a037ed84023f320ce2c9 Mon Sep 17 00:00:00 2001 From: Daniel Beddoe Date: Fri, 18 Nov 2022 11:55:41 +0000 Subject: [PATCH] Allow document type definitions to be included when parsing XML for body matching Fixes: issue #237 --- .../scalapact/shared/matchir/MatchIr.scala | 14 +++++++++++- .../shared/matchir/MatchIrSpec.scala | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/scalapact-shared/src/main/scala/com/itv/scalapact/shared/matchir/MatchIr.scala b/scalapact-shared/src/main/scala/com/itv/scalapact/shared/matchir/MatchIr.scala index cfea2be2..91be782b 100644 --- a/scalapact-shared/src/main/scala/com/itv/scalapact/shared/matchir/MatchIr.scala +++ b/scalapact-shared/src/main/scala/com/itv/scalapact/shared/matchir/MatchIr.scala @@ -8,10 +8,15 @@ import com.itv.scalapact.shared.utils.Helpers.{ safeStringToDouble } +import javax.xml.parsers.SAXParserFactory import scala.util.Try -import scala.xml.{Elem, Node, XML} +import scala.xml.factory.XMLLoader +import scala.xml.{Elem, Node} object MatchIr { + + private val XML: XMLLoader[Elem] = createXMLParser() + def fromXmlString(xmlString: String): Option[IrNode] = Try(XML.loadString(xmlString)).toOption.map(fromXml) @@ -21,6 +26,13 @@ object MatchIr { def fromJSON(fromJson: String => Option[IrNode])(jsonString: String): Option[IrNode] = fromJson(jsonString) + private def createXMLParser(): XMLLoader[Elem] = { + val sAXParserFactory = SAXParserFactory.newInstance() + sAXParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + val saxParser = sAXParserFactory.newSAXParser() + xml.XML.withSAXParser(saxParser) + } + private def convertAttributes(attributes: Map[String, String], pathToParent: IrNodePath): IrNodeAttributes = attributes.toList.reverse .map { diff --git a/tests-with-deps/src/test/scala/com/itv/scalapact/shared/matchir/MatchIrSpec.scala b/tests-with-deps/src/test/scala/com/itv/scalapact/shared/matchir/MatchIrSpec.scala index c42a0dd2..cbe4a703 100644 --- a/tests-with-deps/src/test/scala/com/itv/scalapact/shared/matchir/MatchIrSpec.scala +++ b/tests-with-deps/src/test/scala/com/itv/scalapact/shared/matchir/MatchIrSpec.scala @@ -97,6 +97,28 @@ class MatchIrSpec extends AnyFunSpec with Matchers { } + it("should be able to convert xml with a document type definition") { + val xml: String = + """]>""".stripMargin + + val ir: IrNode = + IrNode( + "animals", + IrNode("alligator") + .withAttributes( + IrNodeAttributes( + Map( + "name" -> IrNodeAttribute(IrStringNode("Mary"), IrNodePathEmpty <~ "animals" <~ "alligator" <@ "name") + ) + ) + ) + .withPath(IrNodePathEmpty <~ "animals" <~ "alligator") + .markAsXml + ).withPath(IrNodePathEmpty <~ "animals").markAsXml + + check(MatchIr.fromXmlString(xml).get =<>= ir) + } + it("should be able to convert one node with content") { val xml: String = haddock.toString()