ballerina-platform/ballerina-library

Support union type as expected type for `data.xmldata` module.

prakanth97 opened this issue · 5 comments

Description:
$title

Describe your task(s)

Related Issues (optional):

Suggested Labels (optional):

Suggested Assignees (optional):

In the xml, the content type is always string, but in the data.xmldata module we allow it to convert to a expected basic type. According to the union type algorithm, we convert them into a JSON and then use data.jsondata, parseAsType API to convert that into a expected type.

In the JSON, string source must be converted to string always. If the expected type is non-string for string literal then it is an error. But we have to allow this for xmldata module hence we have to introduce another option allowConvertFromString for parseAsType API

While working on this found a blocker #6659. I will continue this once fix the issue.

While working on this found a blocker #6659. I will continue this once fix the issue.

This issue is fixed with ballerina-platform/module-ballerina-data.xmldata#26

Ballerina types represents the XSD instead of a particular XML. Hence we have to support the complex union type cases which are possible in the XSD. Currently preparing the doc for this.

According to our offline discussion, we concluded that we should support union types. The reason is that the data.xmldata module takes an XML source and converts it to a Ballerina record type. Our concern should be whether the provided source can be converted to the expected type.

Case 1: Union case without namespace

Sample 1:

<service>
    <port name="8000">
        <address location="exampleweb1.com" />
    </port>
    <port name="8008">
        <address location="exampleweb2.com" />
        <id>2345</id>
    </port>
</service>

Ballerina types =>

Option 1:

type Service record {|
    (PortA|PortB)[] port;
|};

type PortA record {|
    @xmldata:Attribute
    string name;
    Address location;
|};

type Address record {|
    string location;
|};

type PortB record {|
    @xmldata:Attribute
    string name;
    Address location;
    int id; 
|};

Option 2:

type Service record {|
    Port[] port;
|};

type Address record {|
    string location;
|};

type Port record {|
    @xmldata:Attribute
    string name;
    Address location;
    int id?;
|};

Given the above sample, both option 1 and option 2 are valid expected types. The module should allow both cases, but for the XSD of the above XML instance, option 2 is the one we have to generate. At the moment, this needs to be considered when Ballerina supports XSD to Ballerina record generation.

Case 2: Union case with namespace

<A xmlns:ns1="example1.com" xmlns:ns2="example2.com">
    <ns1:port>1</ns1:port>
    <ns2:port>1</ns2:port>
</A>

Option 1:

type A record {|
    (B|C)[] port;
|};

@xmldata:Namespace {
    prefix: "ns1",
    uri: "example1.com"
}
type B record {|
    string \#content; 
|};

@xmldata:Namespace {
    prefix: "ns2",
    uri: "example2.com"
}
type C record {|
    string \#content;
|};

Option 2:

type A record {|
    @xmldata:Name {
        value: "port"
    }
    string ns1Port;
    @xmldata:Name {
        value: "port"
    }
    string ns2Port; 
|};

@xmldata:Namespace {
    prefix: "ns1",
    uri: "example1.com"
}
type B record {|
    string \#content; 
|};

@xmldata:Namespace {
    prefix: "ns2",
    uri: "example2.com"
}
type C record {|
    string \#content;
|};

If we take option 1, it allows you to add sequences of ns1:port and ns2:port. Option 2 allows only one of each of those elements. However, both are valid expected types for the provided XML sample. As mentioned above, this is a concern when generating Ballerina records from the XSD and is not part of this module.

Hence I will resume the union type support.

Reference: https://docs.google.com/document/d/1fE6SjAznfFJGMoDzjVTT84qxA5QmiR37C_ulHtKOyv0/edit?usp=sharing