---
title: Serialise segments and elements
summary: Build ordered data elements into EDI text via SegmentBuilder and EdiRecordBuilder.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common.Files
reference_type: package
operation_id: OP-07
trigger: ISegmentData.Build(), EdiSegment.ToString(), or an EDI file write
---

# Serialise segments and elements

`SegmentBuilder` assembles ordered `IEdiDataElement` values (rejecting a duplicate identifying element, omitting nulls), and `EdiRecordBuilder` turns the assembled elements into X12 text, preserving skipped-ordinal positions with `*` placeholders. Every typed segment's `Build()` ([Map a segment to/from a typed segment object](map-segment-to-typed-object.md)) and [Write an EDI interchange file](write-edi-interchange-file.md) depend on this operation.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-07 |
| **Trigger** | `ISegmentData.Build()`, `EdiSegment.ToString()`, `EdiFileWriter.Write`. |
| **Inputs** | Ordered data elements. |
| **Outputs** | EDI text fragment. |
| **Primary components** | `SegmentBuilder`, `EdiRecordBuilder` |
| **Entry point** | `Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs`, `EdiRecordBuilder.cs` |

## Steps

1. `SegmentBuilder(segmentId)` validates the id via delegated `Enforce.ArgumentNotNullOrWhiteSpace` (`Common\SAIF.Common\Classes\Enforce.cs`: throws `ArgumentException` when null/blank) and immediately adds element 0 = segment id ([BR-020](../business-rules.md#br-020-first-element-is-the-segment-identifier), [BR-023](../business-rules.md#br-023-segment-id-must-not-be-blank)).
   > **Origin**: The null/blank-id guard is implemented by [`Enforce.ArgumentNotNullOrWhiteSpace`](../../saif-framework-common/api/SAIF/Enforce.md) in `SAIF.Framework.Common` and invoked directly from this constructor.
2. `Add(index, value)` rejects a second element at index 0 (`ApplicationException "Segment already contains an identifying Element"`) and silently skips `null` values so that empty optional elements are omitted ([BR-022](../business-rules.md#br-022-only-one-identifying-element-at-index-0), [BR-024](../business-rules.md#br-024-null-element-values-are-omitted)).
3. `Add(elementIndex, compositeIndex, value)` creates an `EdiCompositeDataElement` when the parent index is absent, throws `ApplicationException "Element at index {0} is not a composite element"` when the existing parent is not composite, and otherwise calls `SetChildElement` ([BR-025](../business-rules.md#br-025-composite-sub-elements-require-a-composite-parent)).
4. `EdiCompositeDataElement.SetChildElement` adds, updates, or removes (when `value == null`) the child and re-derives `Value` through `EdiRecordBuilder.BuildCompositeDataElementValue` ([BR-026](../business-rules.md#br-026-composite-element-values-joined-with-colon)).
5. `EdiRecordBuilder.BuildSegmentRecord` orders elements by index and emits `*` placeholders for every skipped index so element positions stay aligned, then removes a trailing `*` ([BR-027](../business-rules.md#br-027-skipped-element-ordinals-preserved-with-placeholders)).
6. `BuildCompositeDataElementValue` joins children with `:`, strips the trailing `:`, and appends `*`. `BuildDataElementValue` appends `*` to the value ([BR-026](../business-rules.md#br-026-composite-element-values-joined-with-colon), [BR-028](../business-rules.md#br-028-simple-data-element-terminated-by-asterisk)).
7. `Build(IList<IEdiDataElement>)` validates the list via delegated `Enforce.ArgumentNotNull` and takes the segment id from the element at index 0 ([BR-021](../business-rules.md#br-021-segment-construction-requires-a-non-null-element-list)).
   > **Origin**: The null-list guard is implemented by [`Enforce.ArgumentNotNull`](../../saif-framework-common/api/SAIF/Enforce.md) in `SAIF.Framework.Common`.

## Process flow

```mermaid
flowchart TD
	Start(["new SegmentBuilder(segmentId)"]) --> Validate{"segmentId null/blank?"}
	Validate -->|Yes| Err1([ArgumentException])
	Validate -->|No| AddId["Add identifying element at index 0"]
	AddId --> AddMore["Add(index, value) for further elements"]
	AddMore --> DupCheck{"Second element at index 0?"}
	DupCheck -->|Yes| Err2([ApplicationException])
	DupCheck -->|No| NullCheck{"value is null?"}
	NullCheck -->|Yes| Omit[Element omitted]
	NullCheck -->|No| Keep[Element kept]
	Omit --> Build["EdiRecordBuilder.BuildSegmentRecord"]
	Keep --> Build
	Build --> EndOk([EDI text fragment])
```

## Failure and edge-case behavior
- Null or blank segment id: `ArgumentException` from `Enforce.ArgumentNotNullOrWhiteSpace` ([BR-023](../business-rules.md#br-023-segment-id-must-not-be-blank)).
- Second identifying element added: `ApplicationException("Segment already contains an identifying Element")` ([BR-022](../business-rules.md#br-022-only-one-identifying-element-at-index-0)).
- Composite sub-element added to a simple parent: `ApplicationException("Element at index {0} is not a composite element")` ([BR-025](../business-rules.md#br-025-composite-sub-elements-require-a-composite-parent)).
- Null element list passed to `Build(IList<IEdiDataElement>)`: `ArgumentException` from `Enforce.ArgumentNotNull` ([BR-021](../business-rules.md#br-021-segment-construction-requires-a-non-null-element-list)).

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs
- Common\SAIF.Common.Files\Edi\EdiCompositeDataElement.cs
- Common\SAIF.Common\Classes\Enforce.cs
