XML Escape / Unescape
Escape text for XML element or attribute contexts — or unescape entities and character references — entirely on this device.
Context applies when escaping: it decides which quote character is escaped, and whether tab, newline and carriage return become character references. Off keeps non-ASCII characters literal — still valid in UTF-8 XML; on emits one uppercase-hex reference per code point. A CDATA section carries no references, so it does not apply there.
Press ? for shortcuts
Do it offline:$ sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g' file.txt
How to use it
- Pick Escape to encode a fragment or Unescape to resolve one; the badge reads your paste, preselects a direction, and the s key flips it.
- Set the context — element text, a double-quoted attribute, a single-quoted attribute, or CDATA. Only the quote that would end the value is rewritten, so nothing is encoded that the destination does not need.
- Switch on the non-ASCII option when the receiving file must stay ASCII: every code point above U+007F leaves as one hexadecimal reference.
- Take the output to the clipboard, a .txt download, or a permalink; the permalink asks first when the paste looks credential-shaped.
XML gives you five predefined entities — lt, gt, amp, quot and apos — and no others until a DTD declares them. This page rewrites a text fragment so it can sit inside an element, a double-quoted attribute, a single-quoted attribute or a CDATA section. Unescape runs the other way, resolving those five names plus decimal and hexadecimal character references.
Examples
Ben & Jerry's <note> 5 > 4Ben & Jerry's <note> 5 > 4Four substitutions land in element text: the ampersand, both angle brackets, and the greater-than of the comparison. The apostrophe in Jerry's stays as typed — a quote is only markup inside an attribute.
Ann "Annie" O'Hara sr.Ann "Annie" O'Hara	sr.Here the inner double quotes become quot and the apostrophe is left alone; the single-quoted context reverses that pairing. The tab leaves as a hexadecimal reference, since normalization would flatten it to a space.
<p>café & crème</p><p>café & crème</p>Five named entities and two character references resolve in one pass: the decimal form 233 and the hexadecimal form E8 both return as letters. What reappears is text, not parsed structure.
if (a<b) { x(); } // ]]> done<![CDATA[if (a<b) { x(); } // ]]]]><![CDATA[> done]]>A section copies its payload verbatim, so the less-than in the condition needs no entity. The one sequence it cannot hold is its own terminator, so the wrapper closes and reopens around that greater-than — one split.
Mont Blanc` ` at line 1, column 5 — XML defines only `<` `>` `&` `"` and `'` without a DTD.Edge case: nbsp is an HTML name XML never defines, so unescape stops at the opening column instead of quietly producing U+00A0. The reference   resolves.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Five names, and never a sixth
Without a DTD an XML document knows lt, gt, amp, quot and apos, and nothing more. Names match exactly as written, so a capitalised spelling is reported rather than accepted, and nbsp, copy or mdash is refused at the ampersand.
The greater-than sign is rewritten every time
The grammar only compels an escape inside a CDATA terminator, yet this tool encodes the character in all element and attribute output. That superset matches what Python's saxutils produces, and the reverse direction resolves gt either way.
Attribute values quietly lose tabs and line feeds
A parser normalises whitespace inside an attribute value before your code sees it, turning a literal tab or newline into a space. Both attribute contexts therefore emit them as hexadecimal references, and element text does the same for a carriage return.
Some characters cannot travel at all
The Char production excludes most C0 controls, the two non-characters ending the basic plane, and lone surrogates. No reference smuggles them in, so the input is declined at that offset rather than repaired. XML 1.1 is out of scope.
CDATA hides markup, it does not encode it
Wrapping suits a script or embedded snippet where a wall of entities would be unreadable, and nothing inside is decoded. It buys no protection for a carriage return, normalised away with no escape available; warnings mark them, up to a limit.
Common errors
Input is larger than the 1 MB limit for this tool. For bigger payloads use the CLI: sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g' file.txt- Past a megabyte the paste is declined whole, never trimmed, so offsets still count from the front of what you gave. The named command covers element text at any file size; attribute and CDATA output have no honest one-liner.
`©` at line 1, column 11 — XML defines only `<` `>` `&` `"` and `'` without a DTD.- An entity name arrived that no XML document defines on its own, usually because the fragment was really HTML. Declare it in a DTD at the destination, or use a numeric reference, which needs no declaration.
`U+0000` at line 1, column 4 — XML 1.0 cannot carry this character, not even as a character reference.- A code point outside the Char production reached the input, often a stray control from a binary paste. Strip it upstream: no context here, CDATA included, can carry it, so the transform stops rather than invent a stand-in.
FAQ
Why is rejected when I unescape?
That name belongs to HTML's entity table, which XML does not inherit. A standalone fragment recognises exactly five names, so anything else must be declared in a DTD or written numerically as  .
How does XML escaping differ from HTML escaping?
HTML recognises well over two thousand entity names and forgives a missing semicolon in many; XML recognises five and requires the terminator. Use the HTML Escape and HTML Decode pages for browser markup, this one for a strict parser.
When should I wrap content in CDATA instead of escaping it?
Wrap when a human must read the payload — SQL, a shell snippet, embedded markup — and entity noise would bury it. Use entities for short values, for attributes, and where the consumer may strip sections.
Does this handle emoji and other astral characters?
Yes, and by default they pass through untouched as legal content. With the non-ASCII option on a rocket becomes one reference, 🚀 — one per code point, not the half-values UTF-16 formats emit.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Re-run the current direction.
- ⌘/Ctrl + S
- Save the output as a .txt download.
- ⌘/Ctrl + C
- Copy the output, or a selection if you made one.
- ⌘/Ctrl + Shift + C
- Copy the whole output despite a selection.
- s
- Flip escape and unescape; suppressed in fields, mid-composition and under the single-key kill switch.
- t
- Step to the next theme, under those same guards.
- ? or ⌘/Ctrl + /
- Show the shortcut overlay, conflicts named.
- Esc
- Close the topmost overlay, input untouched.