Сопоставить дополнительные символы Юникода с BMP (если возможно)

Я столкнулся с проблемой, заключающейся в том, что мой синтаксический анализатор XML (VTD-XML) не может обрабатывать дополнительные символы Юникода (пожалуйста, исправьте, если я уже здесь не прав). Кажется, парсер использует только младшие 16 бит таких символов.

Я не могу переключиться на другой парсер в проекте, которым я занят. Я анализирую тезисы Medline ( https://www.ncbi.nlm.nih.gov/pubmed), и кажется, что за последний год были добавлены документы, содержащие дополнительные символы (например, https://www.ncbi.nlm.nih.gov/pubmed/?term=26855708, раздел "Концы результатов").

В качестве быстрого и грязного исправления я просто удалил бы все символы выше 0xFFFF из документов. Очевидно, что это разрушит некоторые выражения в текстах документов, и поэтому я не очень доволен этим решением.

Поскольку я не могу изменить синтаксический анализатор, мне было интересно, существует ли какая-либо возможность сопоставить дополнительные символы с символами в BMP, которые могут иметь глиф с похожим внешним видом, если таковой существует.

Конечно, я приветствую любую другую идею. Было бы даже неплохо заменить дополнительные символы каким-то заполнителем, а затем вернуть исходный символ обратно, но это кажется подверженным ошибкам. Лучшие идеи?

Изменить: Вот несколько - надеюсь - минимальный пример того, как эта проблема возникает с VTD-XML:

@Test
public void parseUnicodeBeyondBMP() throws NavException, FileNotFoundException, IOException, EncodingException, EOFException, EntityException, ParseException {
    // character codpoint 0x10400
    String unicode = "<supplementary>\uD801\uDC00</supplementary>";
    byte[] unicodeBytes = unicode.getBytes();
    assertEquals(unicode, new String(unicodeBytes, "UTF-8"));

    VTDGen vg = new VTDGen();
    vg.setDoc(unicodeBytes);
    vg.parse(false);
    VTDNav vn = vg.getNav();
    long fragment = vn.getContentFragment();
    int offset = (int) fragment;
    int length = (int) (fragment >> 32);
    String originalBytePortion = new String(Arrays.copyOfRange(unicodeBytes, offset, offset+length));
    String vtdString = vn.toRawString(offset, length);
    // this actually succeeds
    assertEquals("\uD801\uDC00", originalBytePortion);
    // this fails ;-( the returned character is Ѐ, codepoint 0x400, thus the high surrogate is missing
    assertEquals("\uD801\uDC00", vtdString);
}

0 ответов

Другие вопросы по тегам