diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 7c9e3b67..9cef1b0d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -124,3 +124,4 @@ dependencies = [ modules = [ {org = "ballerina", packageName = "time", moduleName = "time"} ] + diff --git a/ballerina/tests/fromXml_test.bal b/ballerina/tests/fromXml_test.bal index 6033b2c2..08ad4f4b 100644 --- a/ballerina/tests/fromXml_test.bal +++ b/ballerina/tests/fromXml_test.bal @@ -3635,3 +3635,60 @@ function testXmlToRecordWithInvalidExpectedTypeForText() { test:assertTrue(rec6 is Error); test:assertEquals((rec6).message(), "unsupported input type"); } + +@test:Config { + groups: ["fromXml"] +} +function testXmlToRecordWithInvalidExpectedTypeForAttributes() { + xml value = xml `1`; + record {int[] id;}|error rec = parseAsType(value); + test:assertTrue(rec is Error); + test:assertEquals((rec).message(), "attribute 'id' cannot be converted into the array type 'int[]'"); + + xml value2 = xml ` + 1 + 2 + 3 + `; + + record {int[] id;}|error rec2 = parseAsType(value2); + test:assertEquals(rec2, {id:[1,2,3]}); + + xml value3 = xml `3`; + record {record{int[] id;} b;}|error rec3 = parseAsType(value3); + test:assertTrue(rec3 is Error); + test:assertEquals((rec3).message(), "attribute 'id' cannot be converted into the array type 'int[]'"); + + xml value4 = xml ` + 1 + 2 + 3 + `; + record {record{int[] id;}[] id;}|error rec4 = parseAsType(value4); + test:assertTrue(rec4 is Error); + test:assertEquals((rec4).message(), "attribute 'id' cannot be converted into the array type 'int[]'"); + + xml value5 = xml `1`; + record {map id;}|error rec5 = parseAsType(value5); + test:assertTrue(rec5 is Error); + test:assertEquals((rec5).message(), "attribute 'id' cannot be converted into the array type 'map'"); + + xml value6 = xml `3`; + record {record{map id;} b;}|error rec6 = parseAsType(value6); + test:assertTrue(rec6 is Error); + test:assertEquals((rec6).message(), "attribute 'id' cannot be converted into the array type 'map'"); + + xml value7 = xml `1`; + record {string:RegExp id;}|error rec7 = parseAsType(value7); + test:assertTrue(rec7 is Error); + test:assertEquals((rec7).message(), "unsupported input type"); + + xml value8 = xml ` + 1 + 2 + 3 + `; + record {record{string:RegExp id;}[] id;}|error rec8 = parseAsType(value8); + test:assertTrue(rec8 is Error); + test:assertEquals((rec8).message(), "unsupported input type"); +} diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index efca262d..e3cf856f 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -1012,6 +1012,27 @@ public static String generateStringFromXmlReader(Reader reader) throws IOExcepti return builder.toString(); } + public static boolean isSupportedTypeForAttributes(Type fieldType) { + if (TypeTags.isIntegerTypeTag(fieldType.getTag())) { + return true; + } + + if (TypeTags.isStringTypeTag(fieldType.getTag())) { + return true; + } + + if (TypeTags.isXMLTypeTag(fieldType.getTag())) { + return false; + } + + return switch (fieldType.getTag()) { + case TypeTags.FLOAT_TAG, TypeTags.BOOLEAN_TAG, TypeTags.NULL_TAG, + TypeTags.DECIMAL_TAG, TypeTags.BYTE_TAG, TypeTags.UNION_TAG, TypeTags.ANYDATA_TAG, + TypeTags.ANY_TAG, TypeTags.JSON_TAG -> true; + default -> false; + }; + } + public static boolean isContainsUnionType(Type expType) { if (expType == null) { return false; diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java index 21fa9fd7..07c1b37d 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java @@ -54,7 +54,10 @@ public enum DiagnosticErrorCode { INVALID_SEQUENCE_ANNOTATION("XML_ERROR_0026", "invalid.sequence.annotation"), INVALID_CHOICE_ANNOTATION("XML_ERROR_0027", "invalid.choice.annotation"), INVALID_XSD_ANNOTATION("XML_ERROR_0028", "invalid.xsd.annotation"), - INVALID_XML("XML_ERROR_0029", "invalid.xml"); + INVALID_XML("XML_ERROR_0029", "invalid.xml"), + ATTRIBUTE_CANNOT_CONVERT_INTO_ARRAY_TYPE("XML_ERROR_0031", + "attributes.cannot.convert.to.array.type"), + CANNOT_CONVERT_ATTRIBUTE_TO_ARRAY_TYPE("XML_ERROR_0032", "cannot.convert.attributes.to.array.type"); String diagnosticId; String messageKey; diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index f2cb4a0a..7af07b06 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -841,9 +841,20 @@ private void handleAttributes(BXmlItem xmlItem, BMap currentNod analyzerData.rootRecord); } + Type fieldType = field.getFieldType(); + + if (DataUtils.isRegExpType(fieldType)) { + throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE); + } + + if (!DataUtils.isSupportedTypeForAttributes(TypeUtils.getReferredType(fieldType))) { + throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_ATTRIBUTE_TO_ARRAY_TYPE, + field.getFieldName(), fieldType); + } + try { currentNode.put(StringUtils.fromString(field.getFieldName()), - DataUtils.convertStringToExpType(attributeMap.get(key), field.getFieldType())); + DataUtils.convertStringToExpType(attributeMap.get(key), fieldType)); } catch (Exception e) { // Ignore: Expected type will mismatch when element and attribute having same name. } diff --git a/native/src/main/resources/error.properties b/native/src/main/resources/error.properties index f155b3f1..39f8892c 100644 --- a/native/src/main/resources/error.properties +++ b/native/src/main/resources/error.properties @@ -106,3 +106,5 @@ error.invalid.xsd.annotation=\ error.invalid.xml=\ Invalid XML found: ''{0}'' +error.cannot.convert.attributes.to.array.type=\ + attribute ''{0}'' cannot be converted into the array type ''{1}''