It took a lot of work to get to this policy. The idea is that although PEs are useful (essential, even) for DTD construction and maintenance, that is the only place they are useful, and they shouldn't complicate the lives of non-validating processors. So to achieve this, in the internal subset (the part between the [ and ] in the doctype declaration), you can only use PEs at the "top level". that is to say, this is legal in the internal subset:
<!ENTITY % e1 "<!ELEMENT e1 ANY>"> %e1;
while this is not (but would be in the external subset):
<!ENTITY % e2 "(e3|e4)">
<!ELEMENT e2 %e2;>
Then, to make things even easier, non-validating processors are allowed to skip PE references completely. This, combined, with the fact that in the internal subset, they can only exist at the top level, makes the internal subset very easy indeed to parse.
Back-link to specCopyright © 1998, Tim Bray. All rights reserved.