# The DataWeave <~ Operator: How Angle Brackets Broke 200 Orders

A customer typed "<VIP>" in their notes field. It broke 200 XML orders and I spent 3 hours finding a one-line fix.

**TL;DR**
- User-generated text with angle brackets (`<`, `>`) breaks XML output — the parser treats them as tags
- The `<~` metadata operator with `{cdata: true}` wraps content in CDATA sections
- CDATA preserves angle brackets as literal text: `<![CDATA[text with <VIP>]]>`
- The `<~` operator requires DataWeave 2.5 (Mule 4.5+)
- JSON output silently ignores cdata metadata — no error, no effect

## The Problem: Valid JSON, Invalid XML

We had a Mule flow converting customer orders from JSON to XML for an ERP. Worked for 6 months. Then 200 orders got rejected.

The customer's notes field:

```json
{
  "customer": {
    "name": "Alice Chen",
    "email": "alice@example.com",
    "notes": "Preferred customer since 2020 <VIP>"
  },
  "orderId": "ORD-12345"
}
```

The DataWeave transform:

```dataweave
%dw 2.0
output application/xml
---
order @(id: payload.orderId): {
    customer @(class: "Person", source: "CRM"): {
        name: payload.customer.name,
        email: payload.customer.email,
        notes: payload.customer.notes
    }
}
```

Output XML:

```xml
<order id="ORD-12345">
  <customer class="Person" source="CRM">
    <name>Alice Chen</name>
    <notes>Preferred customer since 2020 <VIP></notes>
  </customer>
</order>
```

The `<VIP>` in the notes became an XML opening tag. No closing `</VIP>` tag. Invalid XML. The ERP rejected the entire batch.

---

100 production-ready DataWeave patterns with tests: [mulesoft-cookbook on GitHub](https://github.com/shakarbisetty/mulesoft-cookbook)

---

## The Fix: The <~ Metadata Operator

```dataweave
%dw 2.0
output application/xml
---
order @(id: payload.orderId): {
    customer @(class: "Person", source: "CRM"): {
        name: payload.customer.name,
        email: payload.customer.email,
        notes: payload.customer.notes <~ {cdata: true}
    }
}
```

Output:

```xml
<order id="ORD-12345">
  <customer class="Person" source="CRM">
    <name>Alice Chen</name>
    <notes><![CDATA[Preferred customer since 2020 <VIP>]]></notes>
  </customer>
</order>
```

The `<~` operator attaches metadata to a value without changing its type. `{cdata: true}` tells the XML writer to wrap the content in a CDATA section. Angle brackets preserved. Valid XML.

## The @() Syntax for XML Attributes

The `@()` syntax adds XML attributes to elements:

```dataweave
customer @(class: "Person", source: "CRM"): { ... }
```

Produces: `<customer class="Person" source="CRM">`. Attributes come from your data, not hardcoded in the schema.

## Trap 1: <~ Only Works for XML Output

I tried using `<~ {cdata: true}` on a JSON API response. Nothing happened. No error. No warning. The output was identical with and without the `<~`.

The cdata metadata is only read by the XML writer. JSON, CSV, and other formats ignore it silently.

## Trap 2: Requires DataWeave 2.5

The `<~` operator was introduced in DataWeave 2.5 (Mule 4.5+). On older runtimes, it throws a parse error.

Before `<~`, the approach was:

```dataweave
notes: payload.customer.notes as String {class: "cdata"}
```

This works on older runtimes but also coerces the type. `<~` is cleaner because it only attaches metadata — the value type stays unchanged.

## What I Do Now

Any field going to XML that could contain user-generated content gets `<~ {cdata: true}`:
- Customer notes
- Product descriptions
- Address fields (street addresses with unit symbols like #)
- Comment fields from ticketing systems

I also run a pre-transformation check: scan text fields for `<`, `>`, `&`. If found, log a warning and ensure CDATA wrapping is active.

---

100 patterns with MUnit tests: [github.com/shakarbisetty/mulesoft-cookbook](https://github.com/shakarbisetty/mulesoft-cookbook)

60-second video walkthroughs: [youtube.com/@SanThaParv](https://www.youtube.com/@SanThaParv?sub_confirmation=1)
