commit 48660ac2b778976be71713799c408df465fa7999
parent 24185a855a81095e265c4f6808cbe56134ac58cb
Author: MS <ms@taler.net>
Date: Mon, 20 Jul 2020 15:47:49 +0200
Fix parser: detect 2+ children cases.
Diffstat:
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/nexus/src/test/kotlin/Iso20022Test.kt b/nexus/src/test/kotlin/Iso20022Test.kt
@@ -3,7 +3,9 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.junit.Test
import org.w3c.dom.Document
import tech.libeufin.nexus.iso20022.*
+import tech.libeufin.util.DestructionError
import tech.libeufin.util.XMLUtil
+import tech.libeufin.util.destructXml
import java.math.BigDecimal
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
@@ -19,6 +21,23 @@ fun loadXmlResource(name: String): Document {
}
class Iso20022Test {
+ @Test(expected = DestructionError::class)
+ fun testUniqueChild() {
+ val xml = """
+ <a>
+ <b/>
+ <b/>
+ </a>
+ """.trimIndent()
+ // when XML is invalid, DestructionError is thrown.
+ val doc = XMLUtil.parseStringIntoDom(xml)
+ destructXml(doc) {
+ requireRootElement("a") {
+ requireOnlyChild { }
+ }
+ }
+
+ }
@Test
fun testTransactionsImport() {
val camt53 = loadXmlResource("iso20022-samples/camt.053/de.camt.053.001.02.xml")
diff --git a/util/src/main/kotlin/XmlCombinators.kt b/util/src/main/kotlin/XmlCombinators.kt
@@ -129,11 +129,11 @@ private fun Element.getChildElements(ns: String, tag: String): List<Element> {
class XmlElementDestructor internal constructor(val d: Document, val e: Element) {
fun <T> requireOnlyChild(f: XmlElementDestructor.(e: Element) -> T): T {
- val child =
- e.getChildElements("*", "*").elementAtOrNull(0)
- ?: throw DestructionError("expected singleton child tag")
- val destr = XmlElementDestructor(d, child)
- return f(destr, child)
+ val children = e.getChildElements("*", "*")
+ if (children.size != 1) throw DestructionError("expected singleton child tag (2+ found)")
+ if (children[0] == null) throw DestructionError("expected singleton child tag (none found)")
+ val destr = XmlElementDestructor(d, children[0])
+ return f(destr, children[0])
}
fun <T> mapEachChildNamed(s: String, f: XmlElementDestructor.(e: Element) -> T): List<T> {