# Working with SOAP and XSD

> An overview of how to connect data sources to Orbital

Source: https://orbitalhq.com/docs/describing-data-sources/soap

Orbital can use SOAP WSDLs to understand what endpoints exist, and how to call them to fetch data.

Orbital uses [Semantic schemas](/docs/introduction#semantic-data-schemas) to describe how data relates between systems. For SOAP WSDLs, this
means embedding references to Taxi types within your SOAP WSDLs.

To do this, we embed Taxi metadata within the WSDL.

## Adding Taxi to WSDL

**Note: Adding types is optional**
By default, Orbital will generate Taxi based off the type information in your WSDL and XSD docs, so adding type metadata is entirely optional

If you want to control the names of the types that are generated, or you'd like to map an attribute or input
to an existing type, then you can add annotations to your WSDL and XSD's

### Namespace Declaration

First, declare the Taxi namespace in your WSDL:

```xml
   <?xml version="1.0" encoding="UTF-8"?>
   <definitions 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
>     xmlns:taxi="http://taxilang.org/" ...>
```


**Note: Namespace URL**
Note the trailing slash in the namespace URL - `http://taxilang.org/` is required.

### Mapping fields to semantic types
By default, Orbital creates new types for each field and response object when reading an XSD or WSDL.

You can modify this behaviour, either pointing to a new type that you define the name for, or to map to an existing type
 
#### Mapping to an existing type
Adding a `taxi:type="com.foo.MyType` into your XSD or WSDL will map field to an existing type:

```xml
   <xs:complexType name="tCurrency">
      <xs:sequence>
         <xs:element name="sISOCode" type="xs:string" 
>           taxi:type="com.orbitalhq.CurrencyIsoCode"/>
         <xs:element name="sName" type="xs:string" 
>           taxi:type="com.orbitalhq.CurrencyName"/>
      </xs:sequence>
   </xs:complexType>
```

#### Mapping to a new type
Adding a `taxi:createType="com.foo.MyType` into your XSD or WSDL will map field to an existing type:

```xml
   <xs:complexType name="tCurrency">
      <xs:sequence>
         <xs:element name="sISOCode" type="xs:string" 
>           taxi:type="com.orbitalhq.CurrencyIsoCode"/>
         <xs:element name="sName" type="xs:string" 
>           taxi:type="com.orbitalhq.CurrencyName"/>
      </xs:sequence>
   </xs:complexType>
```

This is the equivalent of declaring `taxi:type="com.foo.Bar" taxi:create="true"`

## Adding SOAP or XSD sources to your workspace

### Adding SOAP as a standalone project

You can declare a SOAP schema as a standalone project in your [`workspace.conf`](/docs/workspace/overview#workspace-conf-file), either 
reading from an on-disk resource (on the server where Orbital is running), or reading from a Git repo

Use this approach when you have a WSDL that is standalone, and doesn't form part of a broader taxi project.

You can still use [Taxi mappings](#mapping-fields-to-semantic-types) to map fields to new or existing types using
this approach

#### File based projects 
To add a file based SOAP project to your workspace, add it to the `file.projects` section of your `workspace.conf`:

```hocon workspace.conf
   file {
      projects = [
         {
            path: "./wsdl",
            loader: {
               packageType: Soap
               identifier: {
                  organisation: "com.orbitalhq"
                  name: "CountryInfo"
                  version: "0.1.20"
               },
            }
         }
      ]
   }
```

The `path` can be absolute on the server, or relative to the `workspace.conf` file.

Note that the `loader` section needs to be configured:
 * `packageType`: `Soap`
 * `identifier`: This is a package identifier that uniquely identifies this project. Select an `organisation`, `name` and `version` that's meaningful to you. 

#### Git-based projects
To add a file based SOAP project to your workspace, add it to the `file.projects` section of your `workspace.conf`:

```hocon workspace.conf
   git {
      repositories = [
         {
            # Give this repo a name.  
            name=hamilton-taxonomy
            
            # The url (including personal access token) to clone the repo from
            uri="https://alexhamilton:glpat-dundadadadundundun@github.com/orbital/reynolds-pamphlet"
            
            # The branch to monitor
            branch=master
            
            # The path within the git repo (Optional, by default uses the root) 
            path="/a/path/to/a/folder"
            loader: {
               packageType: Soap
               identifier: {
                  organisation: "com.orbitalhq"
                  name: "CountryInfo"
                  version: "0.1.20"
               },
            }
         }
      ]
   }
```

Note that the `loader` section needs to be configured:
 * `packageType`: `Soap`
 * `identifier`: This is a package identifier that uniquely identifies this project. Select an `organisation`, `name` and `version` that's meaningful to you.

Related:
 - [Adding a git repository to your workspace.conf](/docs/workspace/connecting-a-git-repo#adding-a-git-repository-through-config)

### Adding SOAP or XSD in an existing project
If you just want to add your WSDL or XSD files to your existing Taxi project, you can add them as an additionalSources root 
in the `taxi.conf` of your project.

```hocon taxi.conf
   name: com.orbitalhq/soap-demo
   version: 0.2.0
   sourceRoot: src/
>  additionalSources: {
>     "@orbital/wsdl" = "wsdl/*.{wsdl,xsd}"
>  }
```
 
 - The key must be `@orbital/wsdl`
 - The path can be any directory or path relative to your `taxi.conf` file
 - If your SOAP definition consists of only a WSDL, then use a path pattern of `wsdl/*.wsdl`
 - If your SOAP definition is a mix of WSDL and XSD files, use a path pattern of `wsdl/*{.wsdl.xsd}`

## Additional configuration
You can fine-tine the behaviour of how projects are imported by declaring a `xsd.taxi.conf` file
in the same directory as your xsd / wsdl files.

### Overriding import urls
Sometimes, XSDs are declared with invalid import urls. You can override this by providing a set of
updated URLS in the `xsdImportOverrides` section of your `xsd.taxi.conf` file:

For example, this XSD schema declares an invalid import url:

```xml
   <xs:schema xmlns="http://www.fsa.gov.uk/XMLSchema/FSAHSFFeedHP-v2-0"
   	xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mer-meta="fsa-gov-uk:MER:Meta-Data:1"
   	targetNamespace="http://www.fsa.gov.uk/XMLSchema/FSAHSFFeedHP-v2-0"
   	>
>   	<xs:import namespace="http://www.fsa.gov.uk/XMLSchema/FSAFeedCommon-v1-2"
>   		schemaLocation="https://gabriel.fca.org.uk/specifications/MER/DRG/PSD-CommonTypes/v1.2/FSAFeedCommon-v1-2.xsd"/>
```

To override the location this file is resolved from, add an entry to your `xsd.taxi.conf` file:

```hocon xsd.taxi.conf
 xsdImportOverrides: {
   "http://www.fsa.gov.uk/XMLSchema/FSAFeedCommon-v1-2" : "CommonTypes-Schema.xsd"
}
```

### Overriding modifiers
By default, XSD models are imported as:
 - `closed` by default (they can only be returned from API requests)
 - `parameter` if they are inputs to an API call

You can control this by setting the modifiers:

```hocon xsd.taxi.conf
// In this demo, we want to be able to project to our Xsd types.
// By default, tney're tagged as closed, indicating they're returned from services.
// We can override that here.
defaultModelModifiers: []
```

## Examples & resources

 - [Sample SOAP project on Github](https://github.com/orbitalapi/demos/tree/main/soap-demo) Shows importing a SOAP project as a workspace project 
 - [Sample SOAP project using XSD Imports](https://github.com/orbitalapi/demos/tree/main/soap-with-xsd) Shows mixing WSDL with existing taxi sources, and importing XSD files
 - 📖 [Blog post:  Modernizing SOAP APIs](/blog/2023-09-04-modernizing-soap-apis)
