/^/
HardWeb7 min read

XML Tag Regex

Matches a single XML opening, closing, or self-closing tag, including any attributes with double- or single-quoted values.

#xml#web#markup#tag#parsing

Regex Pattern

<\/?[a-zA-Z_][\w:.-]*(?:\s+[a-zA-Z_:][\w:.-]*(?:=(?:"[^"]*"|'[^']*'))?)*\s*\/?>

Default flags: g

Pattern Breakdown

Hover over a token to see what it does.

<\/?[a-zA-Z_][\w:.-]*(?:\s+[a-zA-Z_:][\w:.-]*(?:=(?:"[^"]*"|'[^']*'))?)*\s*\/?>
TokenMeaning
<\/?A literal < followed by an optional / for closing tags
[a-zA-Z_][\w:.-]*The tag name: starts with a letter or underscore, then letters, digits, underscores, colons, dots, or dashes
\s+Required whitespace separating the tag name (or a previous attribute) from the next attribute
[a-zA-Z_:][\w:.-]*An attribute name, using the same naming rules as XML names
=(?:"[^"]*"|'[^']*')An equals sign followed by a double- or single-quoted attribute value
\s*\/?>Optional trailing whitespace, an optional self-closing slash, then the closing angle bracket

Detailed Explanation

What it does

This pattern recognizes one XML tag at a time: an opening tag like <book>, a closing tag like </book>, or a self-closing tag like <book/>, optionally carrying any number of quoted attributes. With the global flag it can be used to pull each tag out of a small, well-formed XML snippet.

Why it works

The optional slash after < covers closing tags, the tag-name character class follows the XML Name production closely enough for typical documents, and the repeated attribute group handles zero or more name="value" pairs separated by whitespace. The trailing \s*\/?> accepts an optional self-closing slash before the final bracket, covering all three tag shapes with one pattern.

Common use cases

  • Quickly extracting tag names or attributes from a small, trusted XML/config snippet
  • Building a lightweight XML tag highlighter in an editor or documentation tool
  • Sanity-checking that a hand-written XML fragment's tags are well-formed before further processing
  • Stripping simple tags out of an XML-like string for a plain-text preview

Edge cases

  • Self-closing tags with attributes, like <img src="x.png" />, are matched because the self-closing slash is checked after the attribute loop
  • Namespaced tag names, like <ns:book>, are matched since colons are allowed in the name character class
  • Attribute values containing the other quote character, like title="it's fine", are matched correctly because each quote style is matched independently
  • A bare < followed by a digit, like <3, is rejected because tag names cannot start with a digit

Limitations

  • Regex cannot correctly parse arbitrary or deeply nested XML: it has no notion of matching open/close pairs, comments, CDATA sections, or namespaces beyond simple name characters — use a real XML parser for anything beyond single-tag matching
  • Attribute values are not unescaped, so entities like &amp; are returned as-is
  • Malformed XML with unbalanced quotes or unusual whitespace can produce partial or incorrect matches

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

<book> </book> <book/>
3 matches

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Fail
Pass
Fail
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const xmlTagRegex = /<\/?[a-zA-Z_][\w:.-]*(?:\s+[a-zA-Z_:][\w:.-]*(?:=(?:"[^"]*"|'[^']*'))?)*\s*\/?>/g;
const tags = '<book title="1984"><author>Orwell</author></book>'.match(xmlTagRegex);

Common Mistakes

Using a naive pattern like <.+> to match tags, which greedily spans from the first < to the last > across an entire multi-tag document

Fix: Use a non-greedy tag-name and attribute structure like this pattern, or better, use an XML/HTML parser for real documents

Assuming this pattern can validate that opening and closing tags are properly nested and matched

Fix: Regex has no memory of previous matches, so nesting/balance checks require a real parser or a stack-based algorithm, not a single regex

Forgetting to escape special regex characters when building tag patterns dynamically from user input

Fix: Escape any dynamically-inserted tag names with a helper (e.g. a manual escape function) before interpolating into the pattern

Performance Notes

  • The attribute group is a bounded repetition of small alternatives, so well-formed tags match in roughly linear time
  • Malformed input with many nearly-matching attribute-like substrings can cause moderate backtracking; keep tags reasonably short when running this in a hot loop
  • Prefer a real XML/HTML parser (e.g. DOMParser, an XML SAX parser) over regex whenever documents are large, untrusted, or deeply nested

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes