13
\$\begingroup\$

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

Introduction

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:

<Apple>

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

<Apple></Apple>

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:

<mango><Apple></mango></Apple>

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

Definitions

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

Tag

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.

Rules

  • 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

Assumptions

  • 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

Falsey

<apple>

<apple></Apple>

<apple></mango>

<apple><mango>

<a><b></a></b>

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

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

<Ketchup flavor=spicy></Ketchup>

<Ap ple></Apple>

Truthy

Text 

<Apple />

<Apple></Apple>

< Apple ></ Apple>

<mango><Apple/></mango>

<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>

Scoring

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.

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

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!

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

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!

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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