Javascript is required
How it worksPublished 2026-07-284 min read

JSON to XML: Mapping Attributes and CDATA Explicitly

A JSON string carries characters but not an XML attribute or CDATA marker. A converter therefore needs an input convention or intermediate model; otherwise placement in an attribute, normal text, or CDATA depends on defaults. This article covers attributes and CDATA, not array conflicts or SOAP.

By: Tiny
JSON to XMLCDATAAttributesEscaping

1. Problem: string content is not one XML representation

The value a < b can be escaped as ordinary XML text or placed in CDATA, while an id may need to be an attribute. The displayed characters can match even though schema types and receiver expectations differ.

2. Minimal reproduction: reserve explicit attribute and CDATA keys

This contract uses attributes for attributes, text for ordinary text, and cdata for CDATA. A node chooses either text or $cdata; attributes always use XML attribute escaping.

const input = {
  message: {
    $attributes: { id: "m-1" },
    $cdata: "if (a < b && c > d) return;",
  },
};
// <message id="m-1"><![CDATA[if (a < b && c > d) return;]]></message>

3. Root cause: CDATA is XML syntax, not a JSON type

JSON.parse and JSON.stringify preserve only a string, not the intention that it was CDATA. Attributes are also not a native JSON layer. Introduce an explicit convention at the boundary and reject a node that declares both ordinary text and CDATA.

4. Recommendation: normalize into an explicit intermediate model

Normalize each node into name, attributes, text, or cdata before calling an XML serializer. Escape ampersands and angle brackets in ordinary text, and quotes in attributes. CDATA cannot contain ]]>; split that sequence instead of emitting invalid XML.

5. Complete code: escape attributes and split CDATA

This code returns an XML content fragment and demonstrates attribute escaping and CDATA splitting. It does not implement namespaces, arrays, or a SOAP envelope.

function escapeAttribute(value: string): string {
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;");
}
function wrapCdata(value: string): string {
  return "<![CDATA[" + value.replaceAll("]]>", "]]]]><![CDATA[>") + "]" + "]>";
}
function messageXml(id: string, script: string): string {
  return "<message id=\"" + escapeAttribute(id) + "\">" + wrapCdata(script) + "</message>";
}
console.log(messageXml("m&1", "if (a < b && c > d) return;"));

6. Incorrect approaches

Wrapping every string in CDATA changes an ordinary-text contract. Treating $cdata as an attribute produces the wrong layer, and emitting ]]> directly terminates CDATA. Escaping < without escaping & can also create malformed or differently interpreted text.

7. Boundaries: mixed content, empty values, and controls

An empty string may mean an empty element, empty CDATA, or an absent field; define the distinction. An element with text and children is mixed content and should not be reordered by a generic object walker. Reject forbidden XML control characters before serialization.

8. Verification

Test &, angle brackets, quotes, ]]> inside CDATA, empty strings, newlines, Unicode, and control characters. Parse the serialized document with an XML parser, compare attribute/text/CDATA characters, and confirm the receiver schema permits that content.

9. FAQ

Can CDATA contain any string? No; ]]> must be split, and XML still disallows some control characters.

Does CDATA have a different parsed value? The characters can be the same, but serialization and receiver contracts may differ.

Can JSON recover original attributes? No; attribute intent must come from an input convention or external schema.

10. Summary

JSON has no attribute or CDATA type, so use an explicit key convention or intermediate model. Escape attributes by XML rules, choose text versus CDATA deliberately, and verify ]]> boundaries, controls, and mixed content.

Sources and further reading

Specifications and references for checking the article’s technical details.

Related articles

Keep exploring

Use the related browser tool to test the workflow with your own sample data.

Open related tool