После изучения нескольких альтернатив выясняется, что NSXMLParser не будет поддерживать объекты, отличные от стандартных объектов <, >, ', " and &
Приведенный ниже код завершается ошибкой, в результате чего NSXMLParserUndeclaredEntityError
.
// Create a dictionary to hold the entities and NSString equivalents
// A complete list of entities and unicode values is described in the HTML DTD
// which is available for download http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent
NSDictionary *entityMap = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"%C", 0x00E8], @"egrave",
[NSString stringWithFormat:@"%C", 0x00E0], @"agrave",
...
,nil];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:YES];
[parser parse];
// NSXMLParser delegate method
- (NSData *)parser:(NSXMLParser *)parser resolveExternalEntityName:(NSString *)entityName systemID:(NSString *)systemID {
return [[entityMap objectForKey:entityName] dataUsingEncoding: NSUTF8StringEncoding];
}
Попытки объявить сущности, добавив в HTML-документ объявления ENTITY, пройдут, однако расширенные сущности не будут возвращены обратно в parser:foundCharacters
, а символы è и à будут удалены.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
[
<!ENTITY agrave "à">
<!ENTITY egrave "è">
]>
В другом эксперименте я создал полностью действительный документ XML с внутренним DTD
<?xml version="1.0" standalone="yes" ?>
<!DOCTYPE author [
<!ELEMENT author (#PCDATA)>
<!ENTITY js "Jo Smith">
]>
<author>< &js; ></author>
Я реализовал метод делегата parser:foundInternalEntityDeclarationWithName:value:;
, и стало ясно, что синтаксический анализатор получает данные сущности, однако parser:foundCharacters
вызывается только для предварительно определенных сущностей.
2010-03-20 12:53:59.871 xmlParsing[1012:207] Parser Did Start Document
2010-03-20 12:53:59.873 xmlParsing[1012:207] Parser foundElementDeclarationWithName: author model:
2010-03-20 12:53:59.873 xmlParsing[1012:207] Parser foundInternalEntityDeclarationWithName: js value: Jo Smith
2010-03-20 12:53:59.874 xmlParsing[1012:207] didStartElement: author type: (null)
2010-03-20 12:53:59.875 xmlParsing[1012:207] parser foundCharacters Before:
2010-03-20 12:53:59.875 xmlParsing[1012:207] parser foundCharacters After: <
2010-03-20 12:53:59.876 xmlParsing[1012:207] parser foundCharacters Before: <
2010-03-20 12:53:59.876 xmlParsing[1012:207] parser foundCharacters After: <
2010-03-20 12:53:59.877 xmlParsing[1012:207] parser foundCharacters Before: <
2010-03-20 12:53:59.878 xmlParsing[1012:207] parser foundCharacters After: <
2010-03-20 12:53:59.879 xmlParsing[1012:207] parser foundCharacters Before: <
2010-03-20 12:53:59.879 xmlParsing[1012:207] parser foundCharacters After: < >
2010-03-20 12:53:59.880 xmlParsing[1012:207] didEndElement: author with content: < >
2010-03-20 12:53:59.880 xmlParsing[1012:207] Parser Did End Document
Я нашел ссылку на учебник по Использование SAX-интерфейса LibXML . xmlSAXHandler
, используемый NSXMLParser
, позволяет определить обратный вызов getEntity
. После вызова getEntity
расширение объекта передается обратному вызову characters
.
NSXMLParser
здесь отсутствует функциональность. Что должно произойти, это то, что NSXMLParser
или delegate
хранят определения сущностей и предоставляют их для обратного вызова xmlSAXHandler
getEntity
. Это явно не происходит. Я отправлю отчет об ошибке.
Между тем, более ранний ответ на выполнение замены строки вполне приемлем, если ваши документы маленькие. Ознакомьтесь с упомянутым выше руководством по SAX, а также с примером приложения XMLPerformance от Apple, чтобы узнать, стоит ли реализовывать собственный синтаксический анализатор libxml
.
Это было весело.