Skip to content

Commit

Permalink
Better handle the case where an xmlValue is a list of elements and so…
Browse files Browse the repository at this point in the history
…me of the tag content is whitespace. No longer require `@XmlIgnoreWhitespace` to be present in that case as parsing the whitespace is not valid.
  • Loading branch information
pdvrieze committed Sep 10, 2024
1 parent d69e147 commit 768babf
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal object ElementSerializer : XmlSerializer<Element2> {
}

override fun deserializeXML(decoder: Decoder, input: XmlReader, previousValue: Element2?, isValueChild: Boolean): Element2 {
require(input.eventType == EventType.START_ELEMENT) { "${input.eventType} can not be deserialized as XML element" }
val document = previousValue?.ownerDocument ?: createDocument(input.name)
val fragment = document.createDocumentFragment()
@Suppress("DEPRECATION")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1181,16 +1181,31 @@ internal open class XmlDecoderBase internal constructor(
EventType.PROCESSING_INSTRUCTION -> {
} // do nothing/ignore

EventType.CDSECT -> { // cdata is never whitespace
// The android reader doesn't check whitespaceness. This code should throw
return valueChild.markSeenOrHandleUnknown {
config.policy.handleUnknownContentRecovering(
input,
InputKind.Text,
xmlDescriptor,
QName("<CDATA>"),
emptyList()
).let { pendingRecovery.addAll(it) }
decodeElementIndex() // if this doesn't throw, recursively continue
}
}
EventType.ENTITY_REF,
EventType.CDSECT,
EventType.IGNORABLE_WHITESPACE,
EventType.TEXT -> {
// The android reader doesn't check whitespaceness. This code should throw
if (input.isWhitespace()) {
if (valueChild != CompositeDecoder.UNKNOWN_NAME && preserveWhitespace) {
val valueKind = xmlDescriptor.getElementDescriptor(valueChild).kind
if (valueKind == StructureKind.LIST || valueKind is PrimitiveKind
) { // this allows all primitives (
var valueDesc = xmlDescriptor.getElementDescriptor(valueChild)
while (valueDesc is XmlListDescriptor && valueDesc.isListEluded) {
valueDesc = valueDesc.getElementDescriptor(0)
}
val outputKind = valueDesc.outputKind
if (outputKind == OutputKind.Text || outputKind == OutputKind.Mixed) { // this allows all primitives (
seenItems[valueChild] = true
return valueChild // We can handle whitespace
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,62 @@ class ElementChildren237 {

@Test
fun testDeserializedElement() {
val extensions = xml.decodeFromString<Base.Extensions>(XMLSTRING)
val extensions = xml.decodeFromString<Extensions>(XMLSTRING)

val extension = assertNotNull(extensions.extension)

assertEquals(1, extension.size)
val extValue = extension.single()

assertEquals("AdVerifications", extValue.type)

val elems = extValue.value
assertEquals(1, elems.size)

val elem = elems.single()
val adVerChildren = elem.childNodes
assertEquals(3, adVerChildren.getLength())

adVerChildren[0].assertWS()
adVerChildren[2].assertWS()
val verification = assertIs<Element>(adVerChildren[1])

assertEquals("Verification", verification.localName)
assertEquals(1, verification.attributes.getLength())
assertEquals("Something", verification.getAttribute("vendor"))

val jsResource = assertIs<Element>(
assertIs<Text>(verification.firstChild).assertWS()
.nextSibling
)
assertEquals("JavaScriptResource", jsResource.localName)
assertEquals(2, jsResource.attributes.getLength())
assertEquals("omid", jsResource.getAttribute("apiFramework"))
assertEquals("true", jsResource.getAttribute("browserOptional"))

val cdata = assertIs<Text>(
jsResource.firstChild.assertWS().nextSibling
)
assertEquals("https://google.com/video.js", cdata.data)
assertNull(cdata.nextSibling.assertWS().nextSibling)


val verParams = assertIs<Element>(
jsResource.nextSibling.assertWS().nextSibling
)
assertEquals("VerificationParameters", verParams.localName)
assertEquals(0, verParams.attributes.getLength())

val keys = assertIs<Text>(
verParams.firstChild.assertWS().nextSibling
)
assertEquals("""{"key":"21649"}""", keys.data )
assertNull(keys.nextSibling.assertWS().nextSibling)
}

@Test
fun testDeserializedElementIgnoreWhitespace() {
val extensions = xml.decodeFromString<ExtensionsIgnoreWS>(XMLSTRING)

val extension = assertNotNull(extensions.extension)

Expand Down Expand Up @@ -89,21 +144,29 @@ class ElementChildren237 {


@Serializable
class Base {
var extensions: Extensions? = null
class Extensions {
var extension: List<Extension>? = null

@Serializable
class Extensions {
var extension: List<Extension>? = null
class Extension {
var type: String? = null

@XmlValue
val value: List<Element> = emptyList()
}
}

@Serializable
@XmlIgnoreWhitespace
class Extension {
var type: String? = null
@Serializable
class ExtensionsIgnoreWS {
var extension: List<Extension>? = null

@Serializable
@XmlIgnoreWhitespace
class Extension {
var type: String? = null

@XmlValue
val value: List<Element> = emptyList()
}
@XmlValue
val value: List<Element> = emptyList()
}
}

Expand Down

0 comments on commit 768babf

Please sign in to comment.