Self-closing tags in XML files

<tag id="foo" />

I noticed that they work with PHP SimpleXML.

But all XML examples I found on the web close them the old way:

<tag id="foo"></tag>

Is there any reason why I should use the old method?


Solution 1:

See the W3C specs for XML and XHTML:

  • http://www.w3.org/TR/xml/#sec-starttags
  • http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict

It depends on the Element Type declaration

An element with no content is said to be empty. The representation of an empty element is either a start-tag immediately followed by an end-tag, or an empty-element tag.

but also

Empty-element tags may be used for any element which has no content, whether or not it is declared using the keyword EMPTY. For interoperability, the empty-element tag SHOULD be used, and SHOULD only be used, for elements which are declared EMPTY.

This means, when your DTD contains something like

<!ELEMENT img EMPTY>

you should use

<img/>

unless you have good reason to use

<img></img>

Note that SHOULD is defined in RFC2119 as

This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.

If you are working with XML that does not have a DTD or Schema, you can also influence how the XML is serialized with a predefined libxml constant:

LIBXML_NOEMPTYTAG (integer): Expand empty tags (e.g. <br/> to <br></br>)

But note that this option is currently just available in the functions DOMDocument::save and DOMDocument::saveXML, so you cannot use it with SimpleXml.

Solution 2:

Yes, it's not as simple as it seems at first.

XSD differences:

First of all, it depends on your data type. If you use an XSD schema definition, which defines the types of your elements, then <element></element> can actually only be used for string types. Because, that's what it is, it is actually an empty string value: "".

Therefore, it is illegal to use <element></element> for an integer, while by contrast <element/> is applicable for all simple types.

JAXB differences:

JAXB (Java XML Binding) has similar quirks. It would map <element/> as different values depending on the target data type:

  • for String, it would be a ""
  • for Integer, it would be a 0.
  • for other types, it would just skip it.

You could be tempted to think that <element/> would resolve to a null value. But you actually need to use <element xsi:nil="true"/> for that. Which I have never ever seen in practice.

HTML:

In HTML there is always that third option of <element> without closing tag. I don't know about you, but several times a day, I have to remind myself that HTML isn't just XML. And that actually means that <br> and <br/> aren't the same thing. You shouldn't use <br/> in HTML, and you shouldn't use <br> in XHTML.

Angular 2+:

But what I really wanted to get to, continuing on the last statement, if you use frameworks like Angular2+ there is another thing to keep in mind.

Without diving too much in detail, Angular replaces custom HTML tags with HTML templates which are linked to components. However it only supports the <element></element> format. You're not allowed to use the <element/> format.

I personally try to avoid the <element/> syntax, because it has all the potential to make things go wrong. (= bad aji).

Solution 3:

When you want to use PHP's xml parser, you can specify actions upon a start tag, close tag, or a complete tag. Based upon your wishes, you might want to have an action specifically on the close tag.

Solution 4:

In certain instances the separate open/close tags are necessary: as an example I've found that <script> tags in HTML need to have separate open/close to work consistently in some browsers. The separate open/close are a bit more verbose but worth it in those instances.

Solution 5:

They are the same for XML, but may be different depending on your usage. For example, in xhtml1.0, there's an official list for tags allowed for self-closing. As long as you do keep your doctype to the correct xhtml one, you should be fine. Check out this question of stackoverflow for a more detailled explanation.