# XML Integration

> Learn how to define XML formats and mappings in Taxi

Source: https://taxilang.org/docs/other-api-specs/xml

## Overview

Taxi provides XML format support through model annotations, enabling:
- XML reading and writing with semantic types
- Element and attribute mapping
- Collection handling
- Expression evaluation

## Describing XML using Taxi

It's possible to model XML structures directly in Taxi.

If you're working with an existing schema - such as an Xsd, you may prefer [adding type definitions into your XSD](#adding-taxi-types-to-an-xsd)

Add the `Xml` annotation to models that represent XML data:

```taxi
> import com.orbitalhq.formats.Xml

> @Xml
  model Person {
     firstName: FirstName inherits String
     lastName: LastName inherits String
  }
```

### Attributes vs Elements

By default, fields are mapped to XML elements. To map a field to an XML attribute:

```taxi
> import com.orbitalhq.formats.Xml
> import lang.taxi.xml.XmlAttribute

> @Xml
  model Actor inherits Person {
>    @XmlAttribute
     id: ActorId
    
     fullName: FullName
  }
```

Results in:
```xml
<?xml version='1.0' encoding='UTF-8'?>
<Actor id="3">
    <fullName>Jimmy Smith</fullName>
</Actor>
```

### Collections

Array fields automatically map to repeated XML elements:

```taxi
> @Xml
  model Movie {
>   actors: Actor[]
  }
```

Results in:
```xml
<?xml version='1.0' encoding='UTF-8'?>
<Movie>
    <actors id="1">
        <firstName>Mel</firstName>
        <lastName>Gibson</lastName>
    </actors>
    <actors id="2">
        <firstName>Jack</firstName>
        <lastName>Spratt</lastName>
    </actors>
</Movie>
```

### Expressions

Models can include computed fields using expressions:

```taxi
>  import com.orbitalhq.formats.Xml
>  import lang.taxi.xml.XmlAttribute
   
>  @Xml
   model Actor {
       firstName: FirstName inherits String
       lastName: LastName inherits String
       fullName: FullName inherits String = FirstName + ' ' + LastName
   }
```

### Expression Handling
- When serializing: Expression values are written as normal elements

## Generating taxi from an Xsd
The taxi compiler will generate a Taxi from an XSD document .

```xml
<xsd:schema 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:taxi="http://taxilang.org/"
  targetNamespace="http://tempuri.org/PurchaseOrderSchema.xsd">
  
  <xsd:complexType name="CountryInfo">
    <xsd:sequence>
      <!-- Create new semantic type -->
      <xsd:element name="ISOCode" type="xsd:string" 
                   taxi:createsType="com.foo.IsoCode"/>
      
      <!-- Reference existing semantic type -->
      <xsd:element name="Name" type="xsd:string" 
                   taxi:type="com.foo.CountryName"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>
```

> **Note: Namespace URL**
>
> Note the trailing slash in the namespace URL - `xmlns:taxi="http://taxilang.org/` is required.

### Adding type annotations

Use the `taxi:type` annotation within your XSD elements to map fields to **existing** types:

```xml
<xsd:complexType name="CountryInfo">
   <xsd:sequence>
      <xsd:element name="ISOCode" type="xsd:string" taxi:type="com.foo.IsoCode"/>
      <xsd:element name="Name" type="xsd:string" taxi:type="com.foo.CountryName"/>
      <xsd:element name="CapitalCity" type="xsd:string" taxi:type="com.foo.CapitalCityName" />
   </xsd:sequence>
</xsd:complexType>
```

Would generate:

```taxi
namespace org.tempuri {
   closed model CountryInfo {
      ISOCode : com.foo.IsoCode
      Name : com.foo.CountryName
      CapitalCity : com.foo.CapitalCityName
   }
}
```

Note that the type definitions for field types are not declared - it's expected these types exist elsewhere in your taxonomy

### Mapping to an new type
Use the `taxi:createType` annotation within your XSD elements to map fields to **new** types, which generates the type definitions as well as the corresponding model.

```xml
<xsd:complexType name="CountryInfo">
   <xsd:sequence>
      <xsd:element name="ISOCode" type="xsd:string" 
        taxi:createType="com.foo.IsoCode"/>
      <xsd:element name="Name" type="xsd:string" 
        taxi:createType="com.foo.CountryName"/>
      <xsd:element name="CapitalCity" type="xsd:string" 
        taxi:createType="com.foo.CapitalCityName" />
   </xsd:sequence>
</xsd:complexType>
```

Would generate:

```taxi
namespace com.foo {
   type IsoCode inherits String
   type CountryName inherits String
   type CapitalCityName inherits String
}

namespace org.tempuri {
   closed model CountryInfo {
      ISOCode : com.foo.IsoCode
      Name : com.foo.CountryName
      CapitalCity : com.foo.CapitalCityName
   }
}
```

### Nullable vs Mandatory fields
Optional elements (minOccurs="0") generate nullable fields:

```xml
<!-- Optional field -->
<xsd:element name="nickname" minOccurs="0" type="xsd:string"/>
```

Generates:
```taxi
nickname : String?  // Nullable
```

Required attributes generate non-nullable fields:

```xml
<xsd:attribute name="OrderDate" type="xsd:date" use="required"/>
```

Generates:
```taxi
@lang.taxi.xml.XmlAttribute 
OrderDate : Date  // Non-nullable
```

### Enums

XSD enumerations become Taxi enums:

```xml
<xsd:simpleType name="MandateClassification1Code">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="FIXE"/>
    <xsd:enumeration value="USGB"/>
    <xsd:enumeration value="VARI"/>
  </xsd:restriction>
</xsd:simpleType>
```

```taxi
enum MandateClassification1Code {
   FIXE,
   USGB,
   VARI
}
```

Enum values with spaces are automatically normalized:

```xml
<xsd:enumeration value="FOO BAR"/>
```

```taxi
enum MandateClassification1Code {
   FOO_BAR("FOO BAR")  // Name normalized, original value preserved
}
```

### Documentation

XSD documentation annotations are preserved in generated Taxi:

```xml
<xsd:attribute name="OrderDate" type="xsd:date">
  <xsd:annotation>
    <xsd:documentation>The date for an order</xsd:documentation>
  </xsd:annotation>
</xsd:attribute>
```

```taxi
[[ The date for an order ]]
@lang.taxi.xml.XmlAttribute
OrderDate : Date?
```

## Xml types and Taxi types

XSD primitive types map to Taxi types:

| XSD Type     | Taxi Type |
|--------------|-----------|
| xsd:string   | String    |
| xsd:integer  | Int       |
| xsd:int      | Int       |
| xsd:long     | Long      |
| xsd:decimal  | Decimal   |
| xsd:double   | Double    |
| xsd:boolean  | Boolean   |
| xsd:date     | Date      |
| xsd:dateTime | DateTime  |
| xsd:time     | Time      |
