Skip to content

Commit d61a7e2

Browse files
committed
Add a strict mode for name matching, not allowing flexible use of the
null namespace.
1 parent 861be1b commit d61a7e2

File tree

6 files changed

+39
-4
lines changed

6 files changed

+39
-4
lines changed

Diff for: Changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Features:
66
relationships will be maintained.
77
- Support checking ordering in reading.
88
- Support ID type attributes with an @XmlId attribute marking them
9+
- Add support for strict attribute name matching (not allowing null namespace)
10+
matchup
911

1012
Fixes:
1113
- For attribute lists, make sure to collapse the whitespace.

Diff for: serialization/api/android/serialization.api

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public class nl/adaptivity/xmlutil/serialization/DefaultXmlSerializationPolicy :
6060
public fun invalidOutputKind (Ljava/lang/String;)V
6161
public fun isListEluded (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
6262
public fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
63+
public fun isStrictNames ()Z
6364
public fun isTransparentPolymorphic (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
6465
public fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
6566
public fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
@@ -87,9 +88,11 @@ public class nl/adaptivity/xmlutil/serialization/DefaultXmlSerializationPolicy$B
8788
public final fun getVerifyElementOrder ()Z
8889
public final fun ignoreNamespaces ()V
8990
public final fun ignoreUnknownChildren ()V
91+
public final fun isStrictAttributeNames ()Z
9092
public final fun setAutoPolymorphic (Z)V
9193
public final fun setEncodeDefault (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$XmlEncodeDefault;)V
9294
public final fun setPedantic (Z)V
95+
public final fun setStrictAttributeNames (Z)V
9396
public final fun setThrowOnRepeatedElement (Z)V
9497
public final fun setTypeDiscriminatorName (Ljavax/xml/namespace/QName;)V
9598
public final fun setUnknownChildHandler (Lnl/adaptivity/xmlutil/serialization/UnknownChildHandler;)V
@@ -547,6 +550,7 @@ public abstract interface class nl/adaptivity/xmlutil/serialization/XmlSerializa
547550
public abstract fun invalidOutputKind (Ljava/lang/String;)V
548551
public abstract fun isListEluded (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
549552
public abstract fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
553+
public abstract fun isStrictNames ()Z
550554
public abstract fun isTransparentPolymorphic (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
551555
public abstract fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
552556
public abstract fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
@@ -609,6 +613,7 @@ public final class nl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$De
609613
public static fun initialChildReorderMap (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lkotlinx/serialization/descriptors/SerialDescriptor;)Ljava/util/Collection;
610614
public static fun invalidOutputKind (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Ljava/lang/String;)V
611615
public static fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
616+
public static fun isStrictNames (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;)Z
612617
public static fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
613618
public static fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
614619
public static fun mapValueName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;

Diff for: serialization/api/jvm/serialization.api

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public class nl/adaptivity/xmlutil/serialization/DefaultXmlSerializationPolicy :
6060
public fun invalidOutputKind (Ljava/lang/String;)V
6161
public fun isListEluded (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
6262
public fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
63+
public fun isStrictNames ()Z
6364
public fun isTransparentPolymorphic (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
6465
public fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
6566
public fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
@@ -87,9 +88,11 @@ public class nl/adaptivity/xmlutil/serialization/DefaultXmlSerializationPolicy$B
8788
public final fun getVerifyElementOrder ()Z
8889
public final fun ignoreNamespaces ()V
8990
public final fun ignoreUnknownChildren ()V
91+
public final fun isStrictAttributeNames ()Z
9092
public final fun setAutoPolymorphic (Z)V
9193
public final fun setEncodeDefault (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$XmlEncodeDefault;)V
9294
public final fun setPedantic (Z)V
95+
public final fun setStrictAttributeNames (Z)V
9396
public final fun setThrowOnRepeatedElement (Z)V
9497
public final fun setTypeDiscriminatorName (Ljavax/xml/namespace/QName;)V
9598
public final fun setUnknownChildHandler (Lnl/adaptivity/xmlutil/serialization/UnknownChildHandler;)V
@@ -547,6 +550,7 @@ public abstract interface class nl/adaptivity/xmlutil/serialization/XmlSerializa
547550
public abstract fun invalidOutputKind (Ljava/lang/String;)V
548551
public abstract fun isListEluded (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
549552
public abstract fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
553+
public abstract fun isStrictNames ()Z
550554
public abstract fun isTransparentPolymorphic (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Z
551555
public abstract fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
552556
public abstract fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
@@ -609,6 +613,7 @@ public final class nl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$De
609613
public static fun initialChildReorderMap (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lkotlinx/serialization/descriptors/SerialDescriptor;)Ljava/util/Collection;
610614
public static fun invalidOutputKind (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Ljava/lang/String;)V
611615
public static fun isMapValueCollapsed (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Lnl/adaptivity/xmlutil/serialization/structure/XmlDescriptor;)Z
616+
public static fun isStrictNames (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;)Z
612617
public static fun mapEntryName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Ljavax/xml/namespace/QName;
613618
public static fun mapKeyName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;
614619
public static fun mapValueName (Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy;Lnl/adaptivity/xmlutil/serialization/structure/SafeParentInfo;Z)Lnl/adaptivity/xmlutil/serialization/XmlSerializationPolicy$DeclaredNameInfo;

Diff for: serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/XMLDecoder.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ internal open class XmlDecoderBase internal constructor(
696696

697697
val containingNamespaceUri = serialName.namespaceURI
698698
// Allow attributes in the null namespace to match candidates with a name that is that of the parent tag
699-
if (isNameOfAttr) {
699+
if (isNameOfAttr && ! config.policy.isStrictNames) {
700700
if (name.namespaceURI.isEmpty()) {
701701
val attrName = normalizedName.copy(namespaceURI = containingNamespaceUri)
702702
nameMap[attrName]?.checkInputType()?.let { return it.checkRepeat() }
@@ -718,7 +718,7 @@ internal open class XmlDecoderBase internal constructor(
718718

719719
// If the parent namespace uri is the same as the namespace uri of the element, try looking for an element
720720
// with a null namespace instead
721-
if (containingNamespaceUri.isNotEmpty() && containingNamespaceUri == name.namespaceURI) {
721+
if (!config.policy.isStrictNames && containingNamespaceUri.isNotEmpty() && containingNamespaceUri == name.namespaceURI) {
722722
nameMap[QName(name.getLocalPart())]?.checkInputType()?.let { return it.checkRepeatAndOrder(inputType) }
723723
}
724724

Diff for: serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/XmlConfig.kt

+1
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ private constructor(
377377
typeDiscriminatorName = QName(XMLConstants.XSI_NS_URI, "type", XMLConstants.XSI_PREFIX)
378378
encodeDefault = XmlEncodeDefault.ANNOTATED
379379
throwOnRepeatedElement = true
380+
isStrictAttributeNames = true
380381
}
381382
}
382383

Diff for: serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/XmlSerializationPolicy.kt

+24-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public interface XmlSerializationPolicy {
4040
public val defaultPrimitiveOutputKind: OutputKind get() = OutputKind.Attribute
4141
public val defaultObjectOutputKind: OutputKind get() = OutputKind.Element
4242

43+
public val isStrictNames: Boolean get() = false
44+
4345
@ExperimentalXmlUtilApi
4446
public val verifyElementOrder: Boolean get() = false
4547

@@ -293,16 +295,30 @@ public fun XmlSerializationPolicy.typeQName(xmlDescriptor: XmlDescriptor): QName
293295
* but the function can silently ignore it as well.
294296
*/
295297
public open class DefaultXmlSerializationPolicy
296-
@ExperimentalXmlUtilApi constructor(
298+
private constructor(
297299
public val pedantic: Boolean,
298300
public val autoPolymorphic: Boolean = false,
299301
public val encodeDefault: XmlEncodeDefault = XmlEncodeDefault.ANNOTATED,
300302
public val unknownChildHandler: UnknownChildHandler = XmlConfig.DEFAULT_UNKNOWN_CHILD_HANDLER,
301303
public val typeDiscriminatorName: QName? = null,
302304
public val throwOnRepeatedElement: Boolean = false,
303305
public override val verifyElementOrder: Boolean = false,
306+
public override val isStrictNames: Boolean,
304307
) : XmlSerializationPolicy {
305308

309+
@Deprecated("Use builder")
310+
@ExperimentalXmlUtilApi
311+
public constructor(
312+
pedantic: Boolean,
313+
autoPolymorphic: Boolean = false,
314+
encodeDefault: XmlEncodeDefault = XmlEncodeDefault.ANNOTATED,
315+
unknownChildHandler: UnknownChildHandler = XmlConfig.DEFAULT_UNKNOWN_CHILD_HANDLER,
316+
typeDiscriminatorName: QName? = null,
317+
throwOnRepeatedElement: Boolean = false,
318+
verifyElementOrder: Boolean = false,
319+
) : this(pedantic, autoPolymorphic, encodeDefault, unknownChildHandler, typeDiscriminatorName, throwOnRepeatedElement, verifyElementOrder, false)
320+
321+
@Deprecated("Use builder")
306322
@ExperimentalXmlUtilApi
307323
public constructor(
308324
pedantic: Boolean,
@@ -316,6 +332,7 @@ public open class DefaultXmlSerializationPolicy
316332
/**
317333
* Stable constructor that doesn't use experimental api.
318334
*/
335+
@Deprecated("Use builder")
319336
@OptIn(ExperimentalXmlUtilApi::class)
320337
public constructor(
321338
pedantic: Boolean,
@@ -362,6 +379,7 @@ public open class DefaultXmlSerializationPolicy
362379
typeDiscriminatorName = (original as? DefaultXmlSerializationPolicy)?.typeDiscriminatorName,
363380
throwOnRepeatedElement = (original as? DefaultXmlSerializationPolicy)?.throwOnRepeatedElement ?: false,
364381
verifyElementOrder = original?.verifyElementOrder ?: false,
382+
isStrictNames = original?.isStrictNames ?: false
365383
)
366384

367385
@OptIn(ExperimentalXmlUtilApi::class)
@@ -373,6 +391,7 @@ public open class DefaultXmlSerializationPolicy
373391
typeDiscriminatorName = builder.typeDiscriminatorName,
374392
throwOnRepeatedElement = builder.throwOnRepeatedElement,
375393
verifyElementOrder = builder.verifyElementOrder,
394+
isStrictNames = builder.isStrictAttributeNames,
376395
)
377396

378397
override fun polymorphicDiscriminatorName(serializerParent: SafeParentInfo, tagParent: SafeParentInfo): QName? {
@@ -774,14 +793,17 @@ public open class DefaultXmlSerializationPolicy
774793
public var typeDiscriminatorName: QName? = null,
775794
public var throwOnRepeatedElement: Boolean = false,
776795
public var verifyElementOrder: Boolean = false,
796+
public var isStrictAttributeNames: Boolean = false,
777797
) {
778798
internal constructor(policy: DefaultXmlSerializationPolicy) : this(
779799
pedantic = policy.pedantic,
780800
autoPolymorphic = policy.autoPolymorphic,
781801
encodeDefault = policy.encodeDefault,
782802
unknownChildHandler = policy.unknownChildHandler,
783803
typeDiscriminatorName = policy.typeDiscriminatorName,
784-
throwOnRepeatedElement = policy.throwOnRepeatedElement
804+
throwOnRepeatedElement = policy.throwOnRepeatedElement,
805+
verifyElementOrder = policy.verifyElementOrder,
806+
isStrictAttributeNames = policy.isStrictNames,
785807
)
786808

787809
public fun ignoreUnknownChildren() {

0 commit comments

Comments
 (0)