diff --git a/ballerina/tests/fromXml_test.bal b/ballerina/tests/fromXml_test.bal
index efc9f44..6ed5ca5 100644
--- a/ballerina/tests/fromXml_test.bal
+++ b/ballerina/tests/fromXml_test.bal
@@ -1589,7 +1589,7 @@ function testXmlWithAttributesAgainstOpenRecord3() returns error? {
}
@test:Config
-function testCommentMiddleInContent() returns error? {
+function testCommentMiddleInContent1() returns error? {
string xmlStr = string `
John Doe
`;
@@ -1604,6 +1604,22 @@ function testCommentMiddleInContent() returns error? {
test:assertEquals(rec2.A, "John Doe");
}
+@test:Config
+function testCommentMiddleInContent2() returns error? {
+ xml xmlVal = xml `
+ John Doe
+ `;
+ record {} rec = check fromXmlWithType(xmlVal);
+ test:assertEquals(rec.length(), 1);
+ test:assertEquals(rec.get("A"), "John Doe");
+
+ record {|
+ string A;
+ |} rec2 = check fromXmlWithType(xmlVal);
+ test:assertEquals(rec2.length(), 1);
+ test:assertEquals(rec2.A, "John Doe");
+}
+
// Negative cases
type DataN1 record {|
int A;
@@ -1871,3 +1887,35 @@ function testXmlToRecordNegative12() {
RecAtt6|error rec = fromXmlWithType(xmlVal);
test:assertEquals((rec).message(), "required attribute 'data' not present in XML");
}
+
+@test:Config {
+ groups: ["fromXmlString"]
+}
+function testCommentMiddleInContentNegative1() {
+ string xmlStr = string `12`;
+ record {|
+ int A;
+ |}|error rec1 = fromXmlStringWithType(xmlStr);
+ test:assertEquals((rec1).message(), "invalid type expected 'int' but found 'string'");
+
+ record {|
+ int...;
+ |}|error rec2 = fromXmlStringWithType(xmlStr);
+ test:assertEquals((rec2).message(), "invalid type expected 'int' but found 'string'");
+}
+
+@test:Config {
+ groups: ["fromXml"]
+}
+function testCommentMiddleInContentNegative2() {
+ xml xmlVal = xml `12`;
+ record {|
+ int A;
+ |}|error rec1 = fromXmlWithType(xmlVal);
+ test:assertEquals((rec1).message(), "invalid type expected 'int' but found 'string'");
+
+ record {|
+ int...;
+ |}|error rec2 = fromXmlWithType(xmlVal);
+ test:assertEquals((rec2).message(), "invalid type expected 'int' but found 'string'");
+}
diff --git a/native/src/main/java/io/ballerina/stdlib/data/utils/DataUtils.java b/native/src/main/java/io/ballerina/stdlib/data/utils/DataUtils.java
index f22d81e..3ca6ab2 100644
--- a/native/src/main/java/io/ballerina/stdlib/data/utils/DataUtils.java
+++ b/native/src/main/java/io/ballerina/stdlib/data/utils/DataUtils.java
@@ -247,6 +247,10 @@ public static boolean isArrayValueAssignable(int typeTag) {
return typeTag == TypeTags.ARRAY_TAG || typeTag == TypeTags.ANYDATA_TAG || typeTag == TypeTags.JSON_TAG;
}
+ public static boolean isStringValueAssignable(int typeTag) {
+ return typeTag == TypeTags.STRING_TAG || typeTag == TypeTags.ANYDATA_TAG || typeTag == TypeTags.JSON_TAG;
+ }
+
public static ArrayType getValidArrayType(Type type) {
return switch (type.getTag()) {
case TypeTags.ARRAY_TAG -> (ArrayType) type;
@@ -707,7 +711,7 @@ private static String addAttributeToRecord(BString prefix, BString uri, String k
}
/**
- * Holds data required for the parsing and traversing.
+ * Holds data required for the traversing.
*
* @since 0.1.0
*/
diff --git a/native/src/main/java/io/ballerina/stdlib/data/xml/XmlParser.java b/native/src/main/java/io/ballerina/stdlib/data/xml/XmlParser.java
index 30b9307..1dc746c 100644
--- a/native/src/main/java/io/ballerina/stdlib/data/xml/XmlParser.java
+++ b/native/src/main/java/io/ballerina/stdlib/data/xml/XmlParser.java
@@ -232,7 +232,15 @@ private void readText(XMLStreamReader xmlStreamReader,
boolean isCData,
XmlParserData xmlParserData) throws XMLStreamException {
Field currentField = xmlParserData.currentField;
- String text = isCData ? xmlStreamReader.getText() : handleTruncatedCharacters(xmlStreamReader);
+ TextValue textValue = new TextValue();
+ String text;
+ if (isCData) {
+ text = xmlStreamReader.getText();
+ } else {
+ handleTruncatedCharacters(xmlStreamReader, textValue);
+ text = textValue.text;
+ }
+
if (text.strip().isBlank()) {
return;
}
@@ -250,6 +258,11 @@ private void readText(XMLStreamReader xmlStreamReader,
String fieldName = currentField.getFieldName();
BString bFieldName = StringUtils.fromString(fieldName);
Type fieldType = TypeUtils.getReferredType(currentField.getFieldType());
+
+ if (textValue.isCommentInTheMiddle && !DataUtils.isStringValueAssignable(fieldType.getTag())) {
+ throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, fieldType, PredefinedTypes.TYPE_STRING);
+ }
+
if (currentNode.containsKey(bFieldName)) {
if (!DataUtils.isArrayValueAssignable(fieldType.getTag())) {
throw DiagnosticLog.error(DiagnosticErrorCode.FOUND_ARRAY_FOR_NON_ARRAY_TYPE, fieldType, fieldName);
@@ -274,15 +287,17 @@ private void readText(XMLStreamReader xmlStreamReader,
}
}
- private String handleTruncatedCharacters(XMLStreamReader xmlStreamReader) throws XMLStreamException {
+ private void handleTruncatedCharacters(XMLStreamReader xmlStreamReader, TextValue textValue)
+ throws XMLStreamException {
StringBuilder textBuilder = new StringBuilder();
while (xmlStreamReader.getEventType() == CHARACTERS) {
textBuilder.append(xmlStreamReader.getText());
if (xmlStreamReader.next() == COMMENT) {
+ textValue.isCommentInTheMiddle = true;
xmlStreamReader.next();
}
}
- return textBuilder.toString();
+ textValue.text = textBuilder.toString();
}
@SuppressWarnings("unchecked")
@@ -623,13 +638,26 @@ private void readTextRest(XMLStreamReader xmlStreamReader,
BString currentFieldName,
boolean isCData,
XmlParserData xmlParserData) throws XMLStreamException {
- String text = isCData ? xmlStreamReader.getText() : handleTruncatedCharacters(xmlStreamReader);
+ TextValue textValue = new TextValue();
+ String text;
+ if (isCData) {
+ text = xmlStreamReader.getText();
+ } else {
+ handleTruncatedCharacters(xmlStreamReader, textValue);
+ text = textValue.text;
+ }
+
if (text.strip().isBlank()) {
return;
}
BString bText = StringUtils.fromString(text);
Type restType = TypeUtils.getReferredType(xmlParserData.restTypes.peek());
+
+ if (textValue.isCommentInTheMiddle && !DataUtils.isStringValueAssignable(restType.getTag())) {
+ throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, restType, PredefinedTypes.TYPE_STRING);
+ }
+
Object currentElement = currentNode.get(currentFieldName);
BMap parent = (BMap) xmlParserData.nodesStack.peek();
Object result = convertStringToRestExpType(bText, restType);
@@ -788,6 +816,21 @@ private QualifiedName getElementName(XMLStreamReader xmlStreamReader) {
return new QualifiedName(qName.getNamespaceURI(), qName.getLocalPart(), qName.getPrefix());
}
+ /**
+ * Represents the content of an XML element.
+ *
+ * @since 0.1.0
+ */
+ static class TextValue {
+ String text;
+ boolean isCommentInTheMiddle = false;
+ }
+
+ /**
+ * Holds data required for the parsing.
+ *
+ * @since 0.1.0
+ */
public static class XmlParserData {
private final Stack