> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt.
# XML-encoded types
> Generate typed XML serializers, strict parsers, and fluent builders for object types that carry OpenAPI xml metadata, in every Fern SDK.
Object types that carry XML encoding metadata are generated as XML-capable models. Each one gets a serializer, a strict parser, and fluent builder methods for its child elements, so SDK users build and read XML documents (for example, telephony markup such as TwiML) through typed code instead of hand-written strings.
Fern generates XML support in TypeScript, Python, Java, C#, Go, Ruby, and PHP SDKs. No `generators.yml` configuration is required: generation is driven entirely by the XML metadata in your API definition. Types without XML metadata are unchanged, and the XML runtime is only added to an SDK when an XML-encoded type references it.
## Define types with XML metadata
Fern reads the OpenAPI [`xml` object](https://spec.openapis.org/oas/v3.1.0#xml-object) on object schemas and their properties. `name` sets the element or attribute name, `attribute: true` emits a property as an XML attribute instead of a child element, and `wrapped: true` wraps an array in a container element. `prefix` and `namespace` are honored as well.
```yaml
components:
schemas:
Garden:
type: object
xml:
name: Garden
properties:
climate:
type: string
xml:
attribute: true
plants:
type: array
items:
$ref: "#/components/schemas/Plant"
xml:
name: Plants
wrapped: true
Plant:
type: object
xml:
name: Plant
properties:
sunlight:
type: string
enum: [full, partial, shade]
xml:
attribute: true
name:
type: string
```
This definition describes documents like:
```xml
Fern
```
Element names, attributes, text bodies, nested and union children, repeated children, wrapped lists, list separators on attributes and text, namespaces, prefixes, and escaping are all honored.
## Generated methods
Every XML-encoded type gets three capabilities, named idiomatically per language:
* **Serialize**: `toXml()` (`to_xml` in Python and Ruby, `ToXml()` in C# and Go) returns the element as an XML string. Root types (types never nested inside another XML type) include the `` declaration.
* **Parse**: `fromXml(xml)` (`from_xml` in Python and Ruby, `FromXml()` in C#, `FromXml()` in Go) parses an XML string back into the model. Parsing is strict: it validates the root element name and scalar and enum values, and rejects malformed input and `DOCTYPE` declarations.
* **Build**: one fluent method per child element type, named after the XML tag (for example, `garden.plant(...)`). Each method constructs the child, appends it, and returns it so children can be chained. A child method gets an `add` prefix (`addPlant`, `add_plant`, `AddPlant`) when its tag collides with a property or method of the parent, or when the name is a reserved word (`addBreak` in TypeScript, `break_` in Python and Ruby).
**`TypeScript`**
```ts TypeScript
const garden = SeedApi.Garden.builder({ climate: "temperate" });
garden.plant("Fern", { sunlight: "full" });
const xml = garden.toXml();
const parsed = SeedApi.Garden.fromXml(xml); // immutable model
const rebuilt = SeedApi.Garden.Builder.fromXml(xml).build(); // populated builder
```
**`Python`**
```python Python
garden = Garden(climate="temperate")
garden.plant("Fern", sunlight="full")
xml = garden.to_xml()
parsed = Garden.from_xml(xml)
```
**`Java`**
```java Java
Garden garden = Garden.builder()
.climate("temperate")
.plant(Plant.builder().name("Fern").sunlight(Sunlight.FULL).build())
.build();
String xml = garden.toXml();
Garden parsed = Garden.fromXml(xml);
Garden rebuilt = Garden.Builder.fromXml(xml).build();
```
**`C#`**
```csharp C#
var garden = new Garden { Climate = "temperate" };
garden.Plant("Fern", sunlight: "full");
var xml = garden.ToXml();
var parsed = Garden.FromXml(xml);
```
**`Go`**
```go Go
garden := &Garden{Climate: "temperate"}
garden.Plant(&Plant{Name: "Fern", Sunlight: SunlightFull})
xml := garden.ToXml()
parsed, err := GardenFromXml(xml)
```
**`Ruby`**
```ruby Ruby
garden = Seed::Types::Garden.new(climate: "temperate")
garden.plant("Fern", sunlight: "full")
xml = garden.to_xml
parsed = Seed::Types::Garden.from_xml(xml)
```
**`PHP`**
```php PHP
$garden = new Garden(['climate' => 'temperate']);
$garden->plant('Fern', ['sunlight' => 'full']);
$xml = $garden->toXml();
$parsed = Garden::fromXml($xml);
```
C#, Go, Ruby, and PHP also expose element-level variants (`ToXElement()`/`FromXElement()`, `ToXmlElement()`/`FromXmlElement()`, `to_xml_element`/`from_xml_element`, `toXmlElement()`/`fromXmlElement()`) for composing documents without re-parsing strings.
## Round-tripping unknown content
Attributes and child elements that the schema doesn't declare aren't dropped. Parsing preserves them (`additionalAttributes`/`additionalChildren` in TypeScript, C#, Ruby, and PHP; `ExtraAttributes`/`ExtraChildren` in Go; `getAdditionalChildren()` in Java; extra attributes and `XmlElement` children in Python) and serialization re-emits them, so `fromXml(model.toXml())` reproduces the original document. An `addChild` method (`add_child` in Python and Ruby, `AddChild` in C# and Go) appends an arbitrary element when building. Undeclared children are emitted after declared ones, so mixed-content ordering isn't preserved.
> Generate typed XML serializers, strict parsers, and fluent builders for object types that carry OpenAPI xml metadata, in every Fern SDK.