Specification: Ballerina XmlData Library
Owners: @daneshk @kalaiyarasiganeshalingam @MadhukaHarith92
Reviewers: @daneshk
Created: 2021/12/10
Updated: 2023/01/31
Edition: Swan Lake
Introduction
This is the specification for the Xmldata standard library of Ballerina language, which provides APIs to perform conversions between XML and JSON/Ballerina records.
The Xmldata library specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant Github tag.
If you have any feedback or suggestions about the library, start a discussion via a GitHub issue or in the Discord server. Based on the outcome of the discussion, the specification and implementation can be updated. Community feedback is always welcome. Any accepted proposal, which affects the specification is stored under /docs/proposals
. Proposals under discussion can be found with the label type/proposal
in Github.
The conforming implementation of the specification is released and included in the distribution. Any deviation from the specification is considered a bug.
Contents
- Overview
- Data structure
- Rules
- Operations
- 4.1. XML to JSON Conversion
- 4.1.1. Sample
- 4.2. XML to Record Conversion
- 4.2.1. Sample
- 4.3. JSON to XML Conversion
- 4.4. Ballerina record/Map to XML Conversion
- 4.5. XML to Ballerina record/Map Conversion
- 4.1. XML to JSON Conversion
1. Overview
This specification elaborates on the functionalities available in the Xmldata library.
This package considers JSON, XML, Ballerina record and Map data structure and creates the mapping for conversion by preserving their information and structure, and provides the following conversion between XML and JSON/Ballerina records/Map.
- XML to JSON Conversion
- XML to Ballerina record Conversion
- JSON to XML Conversion
- To XML Conversion
- From XML Conversion
2. Data Structure
2.1. JSON
JSON is a textual format for representing a single or collection of following values:
- a simple value (string, number, boolean, null)
- an array of values
- an object
2.2. XML
An XML value is a sequence representing the parsed content of an XML element. Values are sequences of zero or more items, where an item is one of the following:
- element
- text item consisting of characters
- processing instruction
- comment
2.3. Map
A map is an unordered collection of key-value pair elements. A map element is a key and value pair that maps one thing to another. The key must in a string. The value can be of a primitive or complex data type.
2.4. Record
A record is just a collection of fields. Record equality works the same as map equality. A record type descriptor describes a type of mapping value by specifying a type separately for the value of each field.
The record can be defined as an open or a closed record according to the requirement. If a closed record is defined, the returned data should have those defined fields with defined types. Otherwise, this is an open record. Hence, the returned data include both defined fields in the record and additional fields by conversion which are not defined in the record.
3. Rules
We have followed some set of rules for every conversion to preserve the information and structure of both input and output.
3.1. Rules for XML to JSON Conversion
The following rules are used during the conversion process:
- The namespaces will be omitted or added by configuring
preserveNamespaces
. - Attributes and namespaces will be treated as regular JSON properties, and these keys have a prefix with a string to differentiate them from regular JSON properties.
- Sequences of two or more similar elements will be converted to a JSON array.
- Text nodes will be converted into a JSON property with the key as
#content
. - PI and comments in the XML will be omitted.
The following table shows a mapping between the different forms of XML, to a corresponding matching JSON representation by considering the above rules.
XML Type | XML Sample | JSON Representation Type | JSON Representation of XML |
---|---|---|---|
Empty element | <e/> | JSON key-Value pair and value is "" | {"e":""} |
Text item | value | String | value |
Comment | <!-- value --> | Empty JSON because it is not considered in this mapping | {} |
PI | <?doc document="book.doc"?> | Empty JSON because it is not considered in this mapping | {} |
Empty sequence | `` | Empty | `` |
XML sequence, with ‘element’s having distinct keys | <key> <key1>value1</key1> <key2>value2</key2> </key> | JSON object | { "key":{ "key1":"value1", "key2":"value2" } } |
XML sequence, with ‘element’s having identical keys | <keys> <key>value1</key> <key>value2</key> <key>value3</key> </keys> | JSON object which contains JSON array | { "keys":{ "key":["value1","value2","value3"] } } |
XML sequence, containing items of type Element and Text | <key> value1 Value2 <key1>value3</key1> <key2>value4</key2> </key> | JSON object with text value and that key is ’#content’ | { "key":{ "#content":"value1 Value2", "key1":"value3", "key2":"value4" } } |
XML with attribute | <foo key="value">5</foo> | JSON object. Here, attribute has ‘@’ prefix | { "foo": { "@key": "value", "#content": "5" } } |
XML with attribute and namespace | <foo key="value" xmlns:ns0="http://sample.com">5</foo> | JSON object. Here, attribute and namespace have ‘@’ prefix | { "foo":{ "@key":"value", "@xmlns:ns0":"<http://sample.com>", "#content":"5" } } |
3.2. Rules for XML to Record Conversion
This conversion also follows all the rules which will be applied during the XML to the JSON conversion process except the attributes and namespaces rule. Here, attributes and namespaces key will be converted with a prefix as _
in the record.
The table shows a mapping of XML with attribute and namespace to JSON.
XML Type | XML Sample | Record Representation Type | Record Representation of XML |
---|---|---|---|
XML with attribute | <foo key="value">5</foo> | JSON object. Here, attribute has ‘_’ prefix. | { "foo": { "_key": "value", "#content": "5" } |
XML with attribute and namespace | <foo key="value" xmlns:ns0="http://sample.com">5</foo> | JSON object. Here, attribute and namespace have ‘_’ prefix. | { "foo":{ "_key":"value", "_xmlns:ns0":"<http://sample.com>", "#content":"5" } } |
3.3. Rules for JSON to XML Conversion
The following rules are used during the conversion process:
- A default root element will be created while the following scenarios:
- When JSON is a JSON array
json data = [ { "@writer": "Christopher", lname: "Nolan", age: 30, address: ["Uduvil"] }, 1 ];
- When JSON data contains multiple key-value pairs
json data = { fname: "John", lname: "Stallone" };
- When JSON is a JSON array
- JSON array entries will be converted to individual XML elements.
- For a JSON primitive value, convert the value as the text node of the XML element.
- If JSON properties' keys have the prefix and that value is the same with
attributePrefix
value which is defined in theJsonOptions
, those will be handled as attributes and namespaces in the XML.
The following table shows a mapping between the different forms of XML, to a corresponding matching JSON representation by considering the above rules.
JSON Type | JSON Sample | XML Representation Type | XML Representation of XML |
---|---|---|---|
JSON object has single key-value and value is "" | {"e":""} | Empty element | <root><e/></root> |
Empty JSON | `` | Empty Sequence | `` |
Single value (string, number, boolean) | value | XML text | value |
Null | null | Empty sequence | `` |
JSON object with single key-value | { "Store": { "name": "Anne", "address": { "street": "Main", "city": "94" } } } | XML sequence | <root> <Store> <name>Anne</name> <address> <street>Main</street> <city>94</city> </address> </Store> </root> |
JSON object with distinct keys | { "key1":"value1", "key2":"value2" } | XML sequence with root tag | <root> <key1>value1</key1> <key2>value2</key2> </root> |
JSON array | [ { "key": "value1" }, value2 ] | XML sequence with root tag | <root> <item> <key>value1</key> </item> <item>value2</item> </root> |
JSON object with key as "#content" | {"#content":"value1"} | XML text | value1 |
JSON object with key prefix as ‘@’ | { "foo": { "@key": "value", "@xmlns:ns0":"<http://sample.com>" } } | XML element with attribute and namespace | <root> <foo key="value" xmlns:ns0="<http://sample.com>"/> </root> |
3.4. Rules between the Map and XML Conversions
The following table shows mapping the XML to the different forms of map representation.
XML Type | XML Sample | Map Type | Output |
---|---|---|---|
XML Element | <key>value</key> | map<BALLERINA_PRIMITIVE_TYPE> | {key: "VALUE_IN_DEFINED_TYPE"} |
XML Element | <key>value</key> | map<BALLERINA_PRIMITIVE_TYPE_ARRAY> | {key: "VALUE_IN_DEFINED_ARRAY_TYPE"} |
XML Element | <key>value</key> | map<xml> | {#content: <key>value</key>} |
XML Element | <key>value</key> | map<json> | {key: "value"} |
XML Sequence | <keys><key>value</key></keys> | map<BALLERINA_PRIMITIVE_TYPE> | ERROR |
XML Sequence | <keys><key>value</key></keys> | map<BALLERINA_PRIMITIVE_TYPE_ARRAY> | ERROR |
XML Sequence | <keys><key>value</key></keys> | map<json> | {keys: {key: "value"} |
XML Sequence | <keys><key>value</key></keys> | map<xml> | {#content: <keys><key>value</key></keys>} |
XML Sequence | <keys><key>value</key></keys> | map<table<map<string>>> | {keys: table [key: "value"]} |
The following table shows mapping the map data to a corresponding matching XML representation.
Map Type | Map Sample | XML |
---|---|---|
map<BALLERINA_PRIMITIVE_TYPE> | {key1: value1, key2: value2} | <root> <key1>value1</key1> <key2>value2</key2> </root> |
map<BALLERINA_PRIMITIVE_ARRAY_TYPE> | {key1: [v1,v2], key2: [v3,v4]} | <root> <key1>value1</key1> <key1>value2</key1> <key2>value3</key2> <key2>value4</key2> </root> |
map<json> | {keys: {key1: value1, key2: value2}} | <root> <keys> <key1>value1</key1> <key2>value2</key2> </keys> </root> |
map<xml> | {keys: xml <key>value</key>} | <root> <keys> <key>value</key> </keys> </root> |
map<table<map<string>>> | {keys: table [{key: "value"}]} | <root> <keys> <key>value</key> </keys> </root> |
map<json[]> | {keys: [{key1: value1},{key2: value2}]} | <root> <keys> <key1>value1</key1> <key2>value2</key2> </keys> </root> |
map<xml[]> | {keys: [xml <key1>value1</key1>, xml <key2>value2</key2>]} | <root> <keys> <key1>value1</key1> <key2>value2</key2> </keys> </root> |
3.5. Rules between the Ballerina record and XML Conversions
Basic Conversion
The following ballerina record definitions are consistent with the OpenAPI definition to map records to XML without any additional configurations.
Ballerina Record Definition | OpenAPI Definition | XML format |
---|---|---|
Record with single field type Root record { string key?; } | components: schemas: Root: type: object properties: key: type: string | <Root> <key>string</key> </Root> |
Record with multiple key type Root record { string key1?; string key2?; } | components: schemas: Root: type: object properties: key1: type: string key2: type: string | <Root> <key1>string</key1> <key2>string</key2> </Root> |
Nested Record type Root record { Store store?; } type Store record { string name?; Address address?; } type Address record { string street?; int city?; } | components: schemas: Root: type: object properties: store type: object properties: name type: string address: type: object properties street: type: string city type: integer | <Root> <store> <name>string</name> <address> <street>string</street> <city>0</city> /address> </store> </Root> |
Array type Root record { string[] key?; } | Root: type: object properties key: type: array items type: string | <Root> <key>string</key> <key>string</key> </Root> |
Record field type as XML type Root record { xml key?; } | components: schemas Root: type: object properties key: type: object | <Root> <key> xml object </key> </Root> |
Record field type as table table<map type Root record { table key?; } | components: schemas: Root: type: object properties: key: type: array items type: object | <Root> <key>xml object</key> <key>xml object</key> </Root> |
Required Field type Root record { int id; string uname; string name?; } | components: schemas: root: type: object properties: id type: integer uname: type: string name: type: string required: - id - uname | <Root> <id>0</id> <uname>string</uname> <name>string</name> </Root> |
Close record type Person record {| string name; |}; | components: schemas Person: type: object properties name: type: string required - name additionalProperties: false | <Preson> <name>string</name> </Person> |
open record type Person record { string name; }; | components: schemas Person: type: object properties name: type: string required - name additionalProperties: true | <Preson> <name>string</name> <id>string</id> </Person> |
Union Type Field type Location record { string|Address address?; } type Address record { int id; string uname; string name?; } | components: schemas Location: type: object properties: key oneOf - $ref: '#/components/schemas/Address' - type: string Address: type: object properties: id: type: integer username: type: string name: type: string required: - id - uname | <Location> <address> <id>0</id> <uname>string</uname> <name>string</name> </address> </Location> OR <Location> <address>string</address> </Location> |
Conversion with Attributes and Namespaces
The OpenAPI definition has metadata objects that allow for more fine-tuned XML model definitions. You can find those here. https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#fixed-fields-22
So, In Ballerina, we are going to introduce some annotations to support this metadata.
OpenAPI metadata | OpenAPI Definition | Ballerina Record Definition with annotation | XML format |
---|---|---|---|
XML Name Replacement | components: schemas: animals: type: object properties: id: type: integer xml: name: ID xml: name: animal | @xmldata:name { value: animal } type animals record { @xmldata:name{ value: ID } string id?; }; | <animal> <ID>0</ID> </animal> |
XML Attribute | components: schemas: Pline: type: object properties: discount: type: string xml: attribute: true | type Pline record { @xmldata:attribute int discount?; }; | <Pline discount= "string"> </Pline> |
XML Namespace | components: schemas: Root type: object xml: prefix: ns0 namespace: 'http://www.w3.org/' | @xmldata:namespace { prefix:"nso", uri = "http://www.w3.org/" } type Root record {}; | <ns0:Root xmlns:ns0 = "http://www.w3.org/"> </ns0:Root> |
XML Namespace and Prefix | components: schemas: Pline: type: object xml: prefix: 'nso' namespace: 'http://www.w3.org/' properties foo: type: string xml: prefix: 'nso' | @xmldata:namespace { prefix: "nso", uri = "http://www.w3.org/" } type Pline record { @xmldata:namespae{ prefix: "nso" } string foo; }; | <nso:Pline xmlns:ns0="http://www.w3.org/"> <nso:foo></nso:foo> </nso:Pline> |
XML Prefix with Namespaces Noted: OpenAPI Specification does not support multiple XML namespaces within a single element. As a workaround, we can define additional namespaces as regular attributes (that is, schema properties with xml.attribute=true) | components: schemas: Root type: object properties key: type: string xmlns:asd enum - 'http://www.w3.org/' xml attribute: true xml: prefix: 'ns0' namespace: 'http://www.w3.org/' | @xmldata:namespace { prefix:"nso", uri = "http://www.w3.org/" } type Root record { string key?; @xmldata:attribute string xmlns:asd = "http://www.w3.org/" ; }; | <ns0:root xmlns:ns0="http://www.w3.org/" xmlns:asd="http://www.w3.org/"> <key>string</key> </ns0:root> |
Signifies whether the array is wrapped or not. | One of the below open API definitions can be used to define the ballerina record array field definition. So, we don’t need to introduce new annotations for wrapped metadata. 1. Unwrap array definition components: schemas: root: type: object properties: root type:array items: type: string 2. Wrap array definition. components: schemas: root: type: array items: type: string xml: wrapped: true | type root record { string[] root?; } | <root> <root>string</root> </root> |
Convert XML element with attributes(Unsupported in OpenAPI)
OpenAPI does not support XML which has elements with attributes. For more info, please see this issue: https://github.com/OAI/OpenAPI-Specification/issues/630
But this use-case is commonly used in XML. Therefore, In Ballerina, we support through special field name #content
like below.
Ballerina Record Definition | XML Sample |
---|---|
type PLine record { ItemCode itemCode?; } type ItemCode record { string discount?; int #content?;// If the value doesn't have a key, can initialize that value with the default ey name #content } | <PLine> <itemCode discount=22%> 200777 </itemCode> </PLine> |
4. Operations
4.1. XML to JSON Conversion
XML to JSON conversion is a mapping between the different forms of XML to a corresponding matching JSON representation.
The following API returns the JSON data to the given XML structure by configuring the XmlOptions
.
public isolated function toJson(xml xmlValue, XmlOptions options = {}) returns json|Error
The XmlOptions
is used to configure the attribute and namespace prefix and add or eliminate the namespace in the JSON data.
public type XmlOptions record { string attributePrefix = "@"; boolean preserveNamespaces = true; };
4.1.1. Sample
xml input = xml `<ns0:bookStore status="online" xmlns:ns0="http://sample.com/test"> <ns0:storeName>foo</ns0:storeName> <ns0:postalCode>94</ns0:postalCode> <ns0:isOpen>true</ns0:isOpen> <ns0:address> <ns0:street>foo</ns0:street> <ns0:city>94</ns0:city> <ns0:country>true</ns0:country> </ns0:address> <ns0:codes> <ns0:code>4</ns0:code> <ns0:code>8</ns0:code> <ns0:code>9</ns0:code> </ns0:codes> </ns0:bookStore> <!-- some comment --> <?doc document="book.doc"?>`;
The JSON representation of the above XML with the default configuration of the above API.
{ "ns0:bookStore": { "ns0:storeName": "foo", "ns0:postalCode": "94", "ns0:isOpen": "true", "ns0:address": { "ns0:street": "No 20, Palm Grove", "ns0:city": "Colombo 03", "ns0:country": "Sri Lanka" }, "ns0:codes": { "ns0:code":["4","8","9"] }, "@xmlns:ns0":"http://sample.com/test", "@status":"online" } }
When attributePrefix
is &
and preserveNamespaces
is false
, the JSON representation of the above XML
{ "bookStore":{ "storeName":"foo", "postalCode":"94", "isOpen":"true", "address":{ "street":"foo", "city":"94", "country":"true" }, "codes":{ "code":["4","8","9"] } } }
4.2. XML to Record Conversion
This conversion is a mapping between the different forms of XML to a corresponding matching Ballerina record representation.
The following API returns the record to the given XML structure by configuring the preserveNamespaces
and returnType
.
public isolated function toRecord(xml xmlValue, boolean preserveNamespaces = true, typedesc<record {}> returnType = <>) returns returnType|Error
4.2.1. Sample
xml input = xml `<ns0:bookStore status="online" xmlns:ns0="http://sample.com/test"> <ns0:storeName>foo</ns0:storeName> <ns0:postalCode>94</ns0:postalCode> <ns0:isOpen>true</ns0:isOpen> <ns0:address> <ns0:street>foo</ns0:street> <ns0:city>94</ns0:city> <ns0:country>true</ns0:country> </ns0:address> <ns0:codes> <ns0:code>4</ns0:code> <ns0:code>8</ns0:code> <ns0:code>9</ns0:code> </ns0:codes> </ns0:bookStore> <!-- some comment --> <?doc document="book.doc"?>`;
The record representation of the above XML with the default configuration of this API.
{ "ns0:bookStore": { "ns0:storeName": "foo", "ns0:postalCode": "94", "ns0:isOpen": "true", "ns0:address": { "ns0:street": "No 20, Palm Grove", "ns0:city": "Colombo 03", "ns0:country": "Sri Lanka" }, "ns0:codes": { "ns0:code":["4","8","9"] }, "_xmlns:ns0":"http://sample.com/test", "_status":"online" } }
If returnType
is configured for the above output, it must be specified in the following format with the open/closed record type.
type BookStores record {| BookStore ns0\:bookStore; |}; type BookStore record {| string ns0\:storeName; string ns0\:postalCode; string ns0\:isOpen; Address ns0\:address; Codes ns0\:codes; string _status; string _xmlns\:ns0; |}; type Address record {| string ns0\:street; string ns0\:city; string ns0\:country; |}; type Codes record {| string[] ns0\:code; |};
When preserveNamespaces
is false
(without namespaces), the output of the above XML.
{ "bookStore":{ "storeName":"foo", "postalCode":"94", "isOpen":"true", "address":{ "street":"foo", "city":"94", "country":"true" }, "codes":{ "code":["4","8","9"] }, "_status":"online" } }
If returnType
is configured for the above output(without namespaces), it must be specified in the following format with the open/closed record type.
type BookStores record {| BookStore bookStore; |}; type BookStore record {| string storeName; string postalCode; string isOpen; Address address; Codes codes; string _status; |}; type Address record {| string street; string city; string country; |}; type Codes record {| string[] code; |};
4.3. JSON to XML Conversion
This conversion provides a mapping between the different forms of JSON, to a corresponding matching XML representation.
The following API returns the JSON data to the given XML structure by configuring the JsonOptions
.
public isolated function fromJson(json jsonValue, JsonOptions options = {}) returns xml?|Error
The JsonOptions
is used to configure the attribute prefix for the JSON and root and array entry tags for XML.
Array entry tag is used to create a tag when JSON array is in without keys.
public type JsonOptions record { string attributePrefix = "@"; string arrayEntryTag = "item"; string rootTag = "root"; };
4.3.1. Sample1
json input = { "ns0:bookStore": { "ns0:storeName": "foo", "ns0:postalCode": "94", "ns0:isOpen": "true", "ns0:address": { "ns0:street": "No 20, Palm Grove", "ns0:city": "Colombo 03", "ns0:country": "Sri Lanka" }, "ns0:codes": { "ns0:code":["4","8","9"] }, "@xmlns:ns0":"http://sample.com/test", "@status":"online", } };
The XML representation of the above JSON with the default configuration of this API.
<ns0:bookStore xmlns:ns0="http://sample.com/test" status="online"> <storeName>foo</storeName> <postalCode>94</postalCode> <isOpen>true</isOpen> <address> <street>No 20, Palm Grove</street> <city>Colombo 03</city> <country>Sri Lanka</country> </address> <codes> <code>4</code> <code>8</code> <code>9</code> </codes> </ns0:bookStore>
4.3.2. Sample2
json input = { "books": [ [ { "&xmlns:ns0": "http://sample.com/test", "&writer": "Christopher", "bookName": "book1", "bookId": 101 } ], [ { "@writer": "John", "bookName": "book2", "bookId": 102 } ] ] };
When attributePrefix
is &
and arrayEntryTag
is list
, the XML representation of the above JSON.
<root> <books> <list xmlns:ns0="http://sample.com/test" writer="Christopher"> <bookName>book1</bookName> <bookId>101</bookId> </list> </books> <books> <list writer="John"> <bookName>book2</bookName> <bookId>102</bookId> </list> </books> </root>
4.4. Ballerina record/Map to XML Conversion
This conversion provides a mapping between the different forms of Ballerina record/Map, to a corresponding matching XML representation.
The following API returns the XML data to the given Ballerina record/Map.
The record has annotations to configure namespaces and attributes,
but other types(map<BALLERINA_PRIMITIVE_TYPE>|map<BALLERINA_PRIMITIVE_TYPE[]>|map
public isolated function toXml(map<anydata> mapValue) returns xml|Error
The following annotations are used to configure the name, namespace, and attribute.
# Defines the new name of the name. # # + value - The value of the new name public type NameConfig record {| string value; |}; # The annotation is used to specify the new name of the existing record name or field name according to the XML format. public annotation NameConfig Name on type, record field;
# Defines the namespace of the XML element # # + prefix - The value of the prefix of the namespace # + uri - The value of the URI of the namespace public type NamespaceConfig record {| string prefix; string uri?; |}; # The annotation is used to specify the namespace's prefix and URI of the XML element. public annotation NamespaceConfig Namespace on type, record field;
# The annotation is used to denote the field that is considered an attribute. public annotation Attribute on record field;
4.4.1. Sample1
@xmldata:Name { value: "Customers" } @xmldata:Namespace { prefix: "ns", uri: "http://sdf.com" } type Customer record { @xmldata:Name { value: "employeeName" } @xmldata:Attribute string ns\:name; int age; }; Customer input = { name: "Asha", age: 10 };
The XML representation of the above Record:
<ns:Customers xmlns:ns="http://sdf.com" ns:employeeName="Asha"> <age>10</age> </ns:Customers>
4.4.2. Sample2
map<string> input = { "series": "Dark", genre: "Sci-Fi" };
The XML representation of the above map:
<root> <series>Dark</series> <genre>Sci-Fi</genre> </root>;
4.5. XML to Ballerina record/Map Conversion
his conversion is a mapping between the different forms of XML to a corresponding matching Ballerina record/Map representation. The following API returns the record/map to the given XML structure. The namespaces and attributes will not be considered a special case.
public isolated function fromXml(xml xmlValue, typedesc<(map<anydata>)> returnType = <>) returns returnType|Error
4.5.1. Sample1
type Commercial record { BookStore bookstore; }; type BookStore record { xml storeName; int postalCode; boolean isOpen; xml address; xml codes; @Attribute string status; @Attribute string 'xmlns\:ns0; }; type Address record { string street; string city; string country; }; type Codes record { int[] item; }; xml input = xml `<bookstore status="online" xmlns:ns0="http://sample.com/test"> <storeName>foo</storeName> <postalCode>94</postalCode> <isOpen>true</isOpen> <address> <street>Galle Road</street> <city>Colombo</city> <country>Sri Lanka</country> </address> <codes> <item>4</item> <item>8</item> <item>9</item> </codes> </bookstore> <!-- some comment --> <?doc document="book.doc"?>`;
The record representation of the above XML with the returned record type as Commercial
.
Commercial output = { bookstore: { storeName: xml `foo`, postalCode: 94, isOpen: true, address: xml `<street>Galle Road</street><city>Colombo</city><country>Sri Lanka</country>`, codes: xml `<item>4</item><item>8</item><item>9</item>`, 'xmlns\:ns0: "http://sample.com/test", status: "online" } };
4.5.2. Sample2
xml xmlData = xml `<Invoice xmlns="example.com" attr="attr-val" xmlns:ns="ns.com" ns:attr="ns-attr-val"> <PurchesedItems> <PLine><ItemCode>223345</ItemCode><Count>10</Count></PLine> <PLine><ItemCode>223300</ItemCode><Count>7</Count></PLine> <PLine><ItemCode discount="22%">200777</ItemCode><Count>7</Count></PLine> </PurchesedItems> <Address xmlns=""> <StreetAddress>20, Palm grove, Colombo 3</StreetAddress> <City>Colombo</City> <Zip>00300</Zip> <Country>LK</Country> </Address> </Invoice>`;
The map
map<json> output = { Invoice: { PurchesedItems: { PLine: [ {ItemCode: "223345", Count: "10"}, {ItemCode: "223300", Count: "7"}, { ItemCode: {"discount": "22%", "#content": "200777"}, Count: "7" } ] }, Address: { StreetAddress: "20, Palm grove, Colombo 3", City: "Colombo", Zip: "00300", Country: "LK", "xmlns": "" }, "xmlns:ns": "ns.com", "xmlns": "example.com", "attr": "attr-val", "ns:attr": "ns-attr-val" } };