private void handleNcrValue(int returnState) throws SAXException {
        if (!isLegalXmlCharValue(value)) {
            errNcrIllegalValueForXml();
        } else {
            /*
             * If one or more characters match the range, then take them all and
             * interpret the string of characters as a number (either
             * hexadecimal or decimal as appropriate).
             */
            if (value <= 0xFFFF) {
                /*
                 * about ((value <= 0x0008) || (value == 0x000B) || (value >=
                 * 0x000E && value <= 0x001F)) -- we already check for
                 * XML-illegal control characters in isLegalXmlCharValue
                 */
                if ((value & 0xF800) == 0xD800) {
                    errNcrSurrogate();
                    emitOrAppendOne(REPLACEMENT_CHARACTER, returnState);
                } else {
                    /*
                     * Otherwise, return a character token for the Unicode
                     * character whose code point is that number.
                     */
                    char ch = (char) value;
                    if (value >= 0xFDD0 && value <= 0xFDEF) {
                        errNcrUnassigned();
                    } else if ((value & 0xFFFE) == 0xFFFE) {
                        ch = errNcrNonCharacter(ch);
                    } else if (value >= 0x007F && value <= 0x009F) {
                        errNcrControlChar();
                    } else {
                        maybeWarnPrivateUse(ch);
                    }
                    bmpChar[0] = ch;
                    emitOrAppendOne(bmpChar, returnState);
                }
            } else if (value <= 0x10FFFF) {
                maybeWarnPrivateUseAstral();
                if ((value & 0xFFFE) == 0xFFFE) {
                    errAstralNonCharacter(value);
                }
                astralChar[0] = (char) (LEAD_OFFSET + (value >> 10));
                astralChar[1] = (char) (0xDC00 + (value & 0x3FF));
                emitOrAppendTwo(astralChar, returnState);
            } else {
                errNcrOutOfRange();
                emitOrAppendOne(REPLACEMENT_CHARACTER, returnState);
            }

            if ((value & 0xF800) == 0xD800) {
                errNcrSurrogate();
                emitOrAppendOne(REPLACEMENT_CHARACTER, returnState);
            } else if (value <= 0xFFFF) {
                /*
                 * Otherwise, return a character token for the Unicode character
                 * whose code point is that number.
                 */
                char ch = (char) value;
                /*
                 * if ((value <= 0x0008) || (value == 0x000B) || (value >=
                 * 0x000E && value <= 0x001F)) { // we already check for
                 * XML-illegal control // characters in isLegalXmlCharValue ch =
                 * errNcrControlChar(ch); }
                 */
                if (value >= 0xFDD0 && value <= 0xFDEF) {
                    errNcrUnassigned();
                } else if ((value & 0xFFFE) == 0xFFFE) {
                    ch = errNcrNonCharacter(ch);
                } else if (value >= 0x007F && value <= 0x009F) {
                    errNcrControlChar();
                } else {
                    maybeWarnPrivateUse(ch);
                }
                bmpChar[0] = ch;
                emitOrAppendOne(bmpChar, returnState);
            } else if (value <= 0x10FFFF) {
                maybeWarnPrivateUseAstral();
                astralChar[0] = (char) (LEAD_OFFSET + (value >> 10));
                astralChar[1] = (char) (0xDC00 + (value & 0x3FF));
                emitOrAppend(astralChar, returnState);
            } else {
                errNcrOutOfRange();
                emitOrAppendOne(REPLACEMENT_CHARACTER, returnState);
            }

        }
    }
Collect a set of attribues and values from the data part of a PI.

<p>
The bulk of this method and associated methods that follow it here are
copied from the nu.validator.htmlparser.impl.Tokenizer class, with
appropriate modifications.
</p>

@see nu.validator.htmlparser.impl.Tokenizer
@see nu.validator.htmlparser.impl.ErrorReportingTokenizer
src/nu/validator/checker/XmlPiChecker.java