Working with other API specs

XML Integration

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

Add the Xml annotation to models that represent XML data:

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:

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

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

Results in:

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

Collections

Array fields automatically map to repeated XML elements:

@Xml
model Movie {
  actors: Actor[]
}

Results in:

<?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:

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 .

<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>

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:

<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:

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.

<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:

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:

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

Generates:

nickname : String?  // Nullable

Required attributes generate non-nullable fields:

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

Generates:

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

Enums

XSD enumerations become Taxi enums:

<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>
enum MandateClassification1Code {
   FIXE,
   USGB,
   VARI
}

Enum values with spaces are automatically normalized:

<xsd:enumeration value="FOO BAR"/>
enum MandateClassification1Code {
   FOO_BAR("FOO BAR")  // Name normalized, original value preserved
}

Documentation

XSD documentation annotations are preserved in generated Taxi:

<xsd:attribute name="OrderDate" type="xsd:date">
  <xsd:annotation>
    <xsd:documentation>The date for an order</xsd:documentation>
  </xsd:annotation>
</xsd:attribute>
[[ The date for an order ]]
@lang.taxi.xml.XmlAttribute
OrderDate : Date?

Xml types and Taxi types

XSD primitive types map to Taxi types:

XSD TypeTaxi Type
xsd:stringString
xsd:integerInt
xsd:intInt
xsd:longLong
xsd:decimalDecimal
xsd:doubleDouble
xsd:booleanBoolean
xsd:dateDate
xsd:dateTimeDateTime
xsd:timeTime
Previous
CSV
Next
Taxi projects