ERROR: The referenced entity has not been defined.

I received the following today when uploading a large XML file via proc metadata:

ERROR: The referenced entity has not been defined.

All my entities had been appropriately escaped (or so I thought):

select (instr);
  when (';') put ';';
  when ('&') put '&';
  when ('<') put '&lt;';
  when ('>') put '&gt;';
  when ("'") put '&apos;';
  when ('"') put '&quot;';
  when ('0A'x) put '&#x0a;';
  when ('0D'x) put '&#x0d;';
  when ('

Eventually I narrowed it down to this:

<UpdateMetadata>
  <Reposid>$METAREPOSITORY</Reposid>
  <Metadata>
    <TextStore id='A5RIITO4.AG000INH' StoredText='&semi;'>
    </TextStore>
  </Metadata>
  <NS>SAS</NS>
  <Flags>268435456</Flags>
</UpdateMetadata>

It seems that the metadata XML parser doesn’t like the HTML &semi entity reference.  On further investigation it appears that XML does not really support HTML-like named references (like the understandable &semi) in favour of hex type codes (such as &#x3b;).  The exception are the following ’main five‘: Screen Shot 2018 12 09 at 14 43 14 300x181

The authoritative discussion of named entities for XML is available here, but in summary - if you are looking to escape the content loaded into metadata XML, the following SAS code is preferred:

select (instr);
  when (';') put '&#x3b;';
  when ('&') put '&amp;';
  when ('<') put '&lt;';
  when ('>') put '&gt;';
  when ("'") put '&apos;';
  when ('"') put '&quot;';
  when ('0A'x) put '&#x0a;';
  when ('0D'x) put '&#x0d;';
  when ('

If you need to update your metadata, you can find a range of useful macros in the SASjsCore library.