XML Tag Regex
Matches a single XML opening, closing, or self-closing tag, including any attributes with double- or single-quoted values.
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.
| Token | Meaning |
|---|---|
| <\/? | 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 & 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.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| 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
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |
Work with this pattern
Take this expression further — test it against your own data, adapt it in the builder, or read up on the syntax behind it.
Regex Tester
Test a regular expression against sample text and see every match highlighted live.
Regex Generator
Build a pattern by clicking blocks — no syntax memorisation required.
Regular Expressions Guide
What regex is, how the syntax works, and the mistakes that trip people up.
Regex Cheat Sheet
Every token, quantifier, and assertion on one printable page.
Python Regex Guide
The re module end to end — search, match, findall, groups, and substitution.
Regex Pattern Library
100+ ready-to-use patterns for email, URLs, dates, IPs, and more.