How do I keep l() from escaping my link's text?
@Kojo's answer is getting a bit crowded and confusing IMHO so let me post my recommended approach here.



'html' => true

The key to the problem is passing the html option to the l() function like this:

&lt;h3&gt;
  &lt;?php print l(
    $fields['title']-&gt;content, 
    'node/' . $fields['nid']-&gt;content, 
    array('html' =&gt; TRUE)
  ); ?&gt;
&lt;/h3&gt;


This tells l() to bypass the check_plain() function which normally escapes the link text.

Security

Using 'html' =&gt; TRUE is a security risk if you are not sure if the author can be trusted (ie. it is user generated content). 

Depending on where the variables in your template come from, $fields['title']-&gt;content may already have been sanitized. You can test this by setting the title to &lt;script&gt;alert('hi');&lt;/script&gt;. Load the page. If you see a javascript popup, you have an XSS vulnerability to fix. Fortunately, Drupal has a couple of functions built in for that.

Solutions for an XSS vulnerability


Use filter_xss(). A filter that only allows a small selection of HTML tags, fixes invalid markup, and filters out XSS risks. Example:

l(filter_xss($unsafe_text), $path, array('html' =&gt; TRUE));

Use filter_xss_admin(). This is a very permissive option, like filter_xss(), but only recommended to filter content entered by trusted site admins. Example:

l(filter_xss_admin($unsafe_text), $path, array('html' =&gt; TRUE));

Use check_markup(). This is the most configurable option. It uses one of your configured text formats, such as "filtered html", to filter out all but the whitelisted html tags (it will call filter_xss() for you). It will also apply other filters enabled on the text format. Make sure you choose a text format which has the "HTML filter" enabled in its configuration. Example:

l(check_markup($unsafe_text), $path, array('html' =&gt; TRUE));