Проблема с кодировкой XML - PullRequest
1 голос
/ 21 апреля 2009

Я хочу знать, существует ли быстрый способ определить, правильно ли XML-документ кодируется в UTF-8 и не содержит ли он символов, которые не допускаются в кодировке XML UTF-8.

<?xml version="1.0" encoding="utf-8"?>

спасибо заранее, George

РЕДАКТИРОВАТЬ1: здесь находится содержимое моего XML-файла, как в текстовой, так и в двоичной форме.

http://tinypic.com/view.php?pic=2r2akvr&s=5

Я пытался использовать такие инструменты, как xmlstarlet, чтобы проверить, результат правильный (недопустимый из-за превышения диапазона UTF-8), но сообщение об ошибке неверно, потому что в моей опубликованной ссылке выше нет символа значение которого 0xDFDD. Есть идеи?

Кстати: я могу отправить файл XML кому угодно, но я не нашел здесь способа загрузить файл в виде вложения. Если кому-то нужен этот файл для анализа, пожалуйста, дайте мне знать.

D:\xmlstarlet-1.0.1-win32\xmlstarlet-1.0.1>xml val a.xml
a.xml:2: parser error : Char 0xDFDD out of allowed range
<URL>student=1砜濏磦</URL>
              ^
a.xml:2: parser error : Char 0xDFDD out of allowed range
<URL>student=1砜濏磦</URL>
              ^
a.xml:2: parser error : internal error
<URL>student=1砜濏磦</URL>
              ^
a.xml:2: parser error : Extra content at the end of the document
<URL>student=1砜濏磦</URL>
              ^
a.xml - invalid

РЕДАКТИРОВАТЬ2: Я использовал инструмент libxml для проверки правильности XML-файла, но встретил ошибку при запуске этого инструмента. Вот снимок экрана. Есть идеи?

http://tinypic.com/view.php?pic=2ildjpe&s=5

ОС - Windows Server 2003 x64.

Ответы [ 5 ]

2 голосов
/ 21 апреля 2009

libxml2 может сделать это, он доступен как библиотека (для интеграции в ваши программы) или через инструмент командной строки xmllint. Вот пример с xmllint:

[Proper file] 
% head test.xml
<?xml version="1.0" encoding="utf-8"?>
<café>Ils s'étaient ...

% xmllint --noout test.xml
% 

[One byte in a multibyte character removed]
% xmllint --noout test.xml
test.xml:2: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xC3 0x74 0x61 0x69
<café>Ils s'Ãtaient ...
             ^
2 голосов
/ 21 апреля 2009
1 голос
/ 22 апреля 2009

Я не знаю, в чем причина вашей проблемы, но это не ограничение UTF-8 или ошибка в процессе кодирования. UTF-8 может кодировать каждый символ, известный Unicode, и проблемные последовательности байтов (ED BF 9D и ED B4 82) действительны - то есть первый байт начинается с 1110, чтобы указать трехбайтовую последовательность, и каждый из двух других байтов начинается с 10, как предполагается, для продолжения байтов. Это значения, которые они пытаются кодировать , которые являются недействительными.

Unicode и ISO / IEC 10646 не присваивают и никогда не будут присваивать символы ни одной из кодовых точек в диапазоне U + D800 – U + DFFF, поэтому отдельное значение кода из суррогатной пары никогда не представляет символ , -Wikipedia

Ваши проблемные символы: U+DFDD и U+DD02. Тот факт, что есть два символа из диапазона, используемого для суррогатных пар, может показаться предполагающим, что они должны были быть суррогатной парой, но это не работает. Это UTF-16, который использует суррогатные пары; UTF-8 будет кодировать символ в виде одной четырехбайтовой последовательности.

Другой возможностью является модифицированный UTF-8 , который действительно кодирует каждый байт суррогатной пары в отдельности. Но это также не работает: суррогатная пара всегда состоит из одного байта из диапазона высоких суррогатов (U+DC00..U+DFFF) и одного байта из диапазона низких суррогатов (U+D800..U+DBFF). Эти персонажи оба из высшего суррогатного диапазона.

Так что, похоже, дело в плохих данных, а не в неправильном кодировании. Было бы очень полезно, если бы мы знали, какими должны быть эти персонажи. В противном случае, некоторая информация о том, какие данные вы ожидаете (например, на каких языках), откуда эти данные поступили, что с ними сделали ... такого рода вещи.

1 голос
/ 21 апреля 2009

Самый простой способ сделать это - просто запустить XML через утилиту командной строки, чтобы выполнить эту проверку.

У меня всегда есть копия XMLStar для подобных вещей. Он сразу укажет, сможет ли он проанализировать ваш XML, и, таким образом, укажет правильность кодировки или нет.

Если вы ищете кодированный метод для этого, просто загрузите XML в ваш XML-анализатор по вашему выбору. Ошибка кодирования немедленно вызовет исключение синтаксического анализатора (так как кодировка неправильная, анализ по определению невозможен)

, например

XmlDocument xDoc = new XmlDocument();

Затем используйте метод load для загрузки документа XML из указанного потока.

xDoc.Load("sampleXML.xml");
1 голос
/ 21 апреля 2009

Полагаю, вы хотите сделать это программно? В этом случае это сильно зависит от того, какой язык программирования вы используете - какой это будет язык?

Например, я использовал этот код раньше в PHP. preg_match позволяет модификатор / u (который, я думаю, специфичен для PHP), который обрабатывает шаблон и строку, с которой он сопоставляется, как UTF-8. Побочным эффектом является то, что вся строка проверяется на валидность UTF-8 каждый раз, когда вы делаете это. HTML / XHTML не позволяет использовать контрольные коды C0 / C1, кроме табуляции, новой строки, пробела и т. Д., Поэтому я также добавил способ проверить их здесь.

function validate($allowcontrolcodes = false)
    // returns true if this is a valid utf-8 string, false otherwise.  
    // if allowcontrolcodes is false (default), then most C0 codes below 0x20, as
    // well as C1 codes 127-159, will be denied - recommend false for html/xml
    {
        if ($this->string=='') return '';
        return preg_match($allowcontrolcodes
            ? '/^[\x00-\x{d7ff}\x{e000}-\x{10ffff}]++$/u'
            : '/^[\x20-\x7e\x0a\x09\x0d\x{a0}-\x{d7ff}\x{e000}-\x{10ffff}]++$/u',
            $this->string) ? true : false;  
    }

Другим способом было бы использовать DOM, который доступен на многих языках. Объект документа DOM имеет метод LoadXML, который загружает документ из строки в формате XML. Это не удастся, если введенный вами документ недопустим в соответствии с какой-либо кодировкой символов, которую он указал, но не будет принудительно применять кодировку UTF-8, но если он был успешным, вы можете проверить свойство «encoding» объекта документа для посмотрим, что это была за кодировка.

...