<p>How can UTF-8 strings (i.e. 8-bit string) be converted to/from XML-compatible 7-bit strings (i.e. printable ASCII with numeric entities)?</p>

<p>i.e. an <code>encode()</code> function such that:</p>

<pre><code>encode("“£”") -&gt; "&amp;#8220;&amp;#163;&amp;#8221;"
</code></pre>

<p><code>decode()</code> would also be useful:</p>

<pre><code>decode("&amp;#8220;&amp;#163;&amp;#8221;") -&gt; "“£”"
</code></pre>

<p>PHP's <code>htmlenties()</code>/<code>html_entity_decode()</code> pair does not do the right thing:</p>

<pre><code>htmlentities(html_entity_decode("&amp;#8220;&amp;#163;&amp;#8221;")) -&gt;
  "&amp;amp;#8220;&amp;pound;&amp;amp;#8221;"
</code></pre>

<p>Laboriously specifying types helps a little, but still returns XML-incompatible named entities, not numeric ones:</p>

<pre><code>htmlentities(html_entity_decode("&amp;#8220;&amp;#163;&amp;#8221;", ENT_QUOTES, "UTF-8"), ENT_QUOTES, "UTF-8") -&gt;
  "&amp;ldquo;&amp;pound;&amp;rdquo;"
</code></pre>

It's a bit of a workaround, but I read a bit about
```
iconv()
```
and i don't think it'll give you numeric entities (not put to the test)
```
```
function decode( $string )
{
  $doc = new DOMDocument( "1.0", "UTF-8" ); 
  $doc->LoadXML( '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<x />', LIBXML_NOENT );
  $doc->documentElement->appendChild( $doc->createTextNode( $string ) );
  $output = $doc->saveXML( $doc );
  $output = preg_replace( '/<\?([^>]+)\?>/', '', $output ); 
  $output = str_replace( array( '<x>', '</x>' ), array( '', '' ), $output );
  return trim( $output );
}
```
```
This however, I have put to the test. I might do the reverse later, just don't hold your breath ;-)