NSXMLParser и байты спецификации
-
20-09-2019 - |
Вопрос
Я получаю свой XML-файл в результате запроса PHP с какого-то сервера.Когда я печатаю полученные данные на консоль, я получаю хорошо структурированный XML-файл.Когда я пытаюсь проанализировать его с помощью NSXMLParser, он возвращает NSXMLParserErrorDomain с кодом 4 — пустой документ.Я видел, что XML-файлы, которые он не мог проанализировать, имели последовательность BOM (маркер порядка байтов) сразу после закрытия знака «>» заголовка xml.Вопрос в том, как избавиться от последовательности спецификации.Я попытался создать строку с этими байтами спецификации следующим образом:
const UInt8 bom[3] = {0xEF, 0xBB, 0xBF};
NSString *bomString = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bom length:3] encoding:NSUTF8StringEncoding];
NSString *noBOMString = [theResult stringByReplacingOccurrencesOfString:bomString withString:@" "];
но это почему-то не работает.Существуют xml-файлы, в которых эта последовательность находится после корневого элемента.В этом случае NSXMLParser успешно анализирует XML.Safari игнорирует эти символы.Итак, отладчик Xcode.Пожалуйста помоги!
Спасибо,
Нава
Решение
Я попытался создать строку с этими байтами спецификации следующим образом:
const UInt8 bom[3] = {0xEF, 0xBB, 0xBF}; NSString *bomString = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bom length:3] encoding:NSUTF8StringEncoding]; NSString *noBOMString = [theResult stringByReplacingOccurrencesOfString:bomString withString:@" "];
но это почему-то не работает.
Убедитесь, что вы указали правильную кодировку при создании экземпляра. noBOMString
.Если данные документа были в формате UTF-8, убедитесь, что вы создали экземпляр строки как UTF-8.Аналогично, если данные были в формате UTF-16, убедитесь, что вы создали экземпляр строки как UTF-16.
Если вы передадите неверную кодировку, либо строка вообще не будет создана (я предполагаю, что это не ваша проблема), либо некоторые символы будут неправильными.Спецификация будет одной из следующих:Если входные данные имеют формат UTF-8 и вы интерпретируете их как MacRoman или ISOLatin1, они появятся в строке как три отдельных символа.Эти три отдельных символа не будут сравниваться с одним символом, являющимся спецификацией.
Другие советы
Я не уверен, что это проблема.У меня был очень похожий опыт, когда файл был закодирован как UTF-8, но в заголовке xml было указано, что это UTF-16.
Из-за несоответствия мне не удалось проанализировать его с той же ошибкой, что и у вас.Однако изменение заголовка xml с UTF-16 на UTF-8 решило мою проблему.
Возможно, вы столкнулись с похожей проблемой.
Что ж, возможно, это не лучший способ избавиться от байтов спецификации, но он работает.Для тех, кто, как я, часами пытался заставить NSXMLParser проглатывать спецификации:Учитывая, что вы получаете свои данные через NSURLConnection и сохраняете их в NSMutableData *webData.
const char bom[3] = {0xEF, 0xBB, 0xBF};
char *data = [webData mutableBytes];
char *cp = data, *pp;
long lessBom = 0;
do {
cp = strstr((const char *)cp, (const char *)bom);
if (cp) {
pp = cp;
cp += 3;
memcpy(pp, cp, strlen(cp));
lessBom += 3;
}
} while (cp != NULL);
NSMutableData *newData = [[NSMutableData alloc] initWithBytes:data length:webData.length - lessBom];
Затем вы создаете свой парсер с помощью newData, и он ПРОСТО РАБОТАЕТ!Буду рад любым комментариям/улучшениям этого кода.