This is based off a previous deleted challenge of mine with the same name


You are tasked with writing a program that returns a truthy or falsey value based on if the input has all its XML-like1 tags appropriately opened and closed and in the right order. Consider the following as input:


This would return a falsey value because the tag is not closed correctly. This:


On the contrary returns a truthy value because it is closed correctly. The program should also check nested tags to make sure they are in the correct position. For example, take this as input:


All the tags are closed correctly, but not in the correct order. Your program must check for correct tag hierarchy and nesting.


Let me define a few things before I get into the rules and assumptions.


A basic XML-style tag. For example: <Apple>. They can have at most, one leading and trailing space (or else it's invalid and falsey), so < Apple > and <Apple> are the same. These tags can also contain attributes like foo="bar" (with required double quotes, or else invalid and falsey), and the attribute name can only contain any alphanumeric character or _, :, -, and .. The attribute names also do not require an attribute value, and values can contain anything except " before the closing double quote. The closing tag must not contain attributes, and no tags should have newlines in them.

Tag Name

Tag names are the tags' names. For example, <Apple>'s tag name is Apple. Tag names can contain the same characters as attribute names, and are case-sensitive. This means <Apple> is not <apple>.

Self-Closing Tag

A regular tag that closes itself such as <Apple /> or <Apple/> (they are the same). The space between the slash and the tag name is allowed.

Plain Text

A string of characters that can contain anything and are not enclosed in < and >.

"Simple" Tag

Either an opening, closing, or self-closing tag.


  • Output may be returned or printed, and input may be taken any way you like
  • Input is a string, consisting of either tags, plain text, or both
  • Your program can be a function or a whole working program

  • Plain text can be anywhere; if the input consists only of plain text, the program should return a truthy value.

  • Recognition of nested tags is required for the program. If a tag is nested in a tag, that nested tag must be closed before the parent is closed, just like regular XML, or else a falsey value should be returned


  • You can assume that input will always be one or more "simple" tag(s)
  • You can assume that input will always follow the format for tags defined above

Test Cases







Text<ul><li></li><ul />

<pear attr=foo></pear attr=foo>

<Ketchup flavor=spicy></Ketchup>

<Ap ple></Apple>



<Apple />


< Apple ></ Apple>


<mango>Text<div class="bar">More text \o/</div></mango>

<food group="fruit">Fruits:<orange :fruit-variety="clementine" /><pear _fruit.type="asian" /></food>

<example foo="abcdefghijklmnopqrstuvwxyz1234567890-/:;()$&@.,?!'" noValue>Any characters allowed! (0.0)</example>


This is , so the shortest code in bytes wins. Standard loopholes are prohibited as usual.

1Note: This is not real XML, but a pseudo-XML with different rules for the challenge. Tag and attribute names differ from specification.

  • \$\begingroup\$ If a tag has more than one space before or after it, do we have to mark it false? \$\endgroup\$
    – JayDepp
    Commented Dec 30, 2016 at 16:45
  • \$\begingroup\$ @JayDepp Yes - let me clarify that in my post \$\endgroup\$
    – Andrew Li
    Commented Dec 30, 2016 at 16:47
  • \$\begingroup\$ Can we use builtins that parse strings to XML? \$\endgroup\$
    – Oliver
    Commented Dec 30, 2016 at 17:05
  • \$\begingroup\$ @obarakon The problem is this isn't necessarily valid XML. See the footnote. \$\endgroup\$
    – Andrew Li
    Commented Dec 30, 2016 at 17:10
  • \$\begingroup\$ Is it correct to say, that this is a truthy input: < : : :><:/><: :=":=:" ::></:>< /:>? \$\endgroup\$ Commented Dec 30, 2016 at 18:02

2 Answers 2


Retina, 76 74 Bytes

+`< ?([-.:\w]+)( ?[-.:\w]+(="[^"]*")?)* ?(/>|>[^<>]*< ?/ ?\1 ?>)


Since I've seen that retina is really good for golfing regexes, I figured I'd try it out. Follows the same logic as my Ruby answer and prints 0 or 1.

Try it online!

  • 1
    \$\begingroup\$ You don't need the M`. If the final stage only has a single part, match mode is implied. \$\endgroup\$ Commented Dec 31, 2016 at 9:24

Ruby (2.3.1), 103 101 100 Bytes

->s{s.sub!(/< ?([-.:\w]+)( ?[-.:\w]+(="[^"]*")?)* ?(\/>|>[^<>]*< ?\/ ?\1 ?>)/,'')&&redo;!(s=~/<|>/)}

Anonymous function called by appending .call("<Apple></Apple>"). Substitutes matching or self closing tags until there arent any, and then returns whether the string has no angle brackets remaining.

Try it online!

  • \$\begingroup\$ This marks <p title="This is a \"test\"."></p> as Falsey, but it shouldn't be. \$\endgroup\$
    – orlp
    Commented Dec 30, 2016 at 21:03
  • \$\begingroup\$ @orlp 'values can contain anything except " before the closing double quote.' \$\endgroup\$
    – JayDepp
    Commented Dec 30, 2016 at 21:05
  • \$\begingroup\$ Oh it's not real XML... \$\endgroup\$
    – orlp
    Commented Dec 30, 2016 at 21:07
  • 1
    \$\begingroup\$ Real XML should never be parsed with regex :) \$\endgroup\$
    – JayDepp
    Commented Dec 30, 2016 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.