2009-10-09 32 views
6

Tôi có một tệp XML sử dụng các thực thể được khai báo nội bộ. Ví dụ:Cách giải quyết tham chiếu đối tượng XML được khai báo nội bộ bằng cách sử dụng NSXMLParser

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

... 

<!ENTITY my_symbol "my symbol value"> 

... 

<my_element> 
    <my_next_element>foo&my_symbol;bar</my_next_element> 
</my_element> 

... 

Sử dụng lớp NSXMLParser, làm cách nào tôi có thể giải quyết tham chiếu thực thể my_symbol?

Từ thử nghiệm, phương thức ủy quyền parser:foundInternalEntityDeclarationWithName:value: sẽ được gọi cho khai báo thực thể my_symbol, với giá trị "my symbol value". Sau đó, khi đạt được thành phần my_next_element, NSXMLParser sẽ gọi phương thức ủy nhiệm parser:didStartElement:namespaceURI:qualifiedName:attributes:.

Trước parser:didEndElement:namespaceURI:qualifiedName: được gọi là cho </my_next_element>, phương pháp parser:foundCharacters: đại biểu sẽ được gọi là hai lần với các dây:

  1. "foo"
  2. "bar"

Tham chiếu my_symbol thực thể được bỏ qua. Điều gì là cần thiết để tham chiếu thực thể được giải quyết?

EDIT:

Loại bỏ các ENTITY tuyên bố my_symbol từ DTD sẽ dẫn đến một NSXMLParserUndeclaredEntityError. Điều này cho thấy rằng khi khai báo thực thể có mặt, và sau đó được tham chiếu trong <my_next_element>, nó đang được chú ý. Đối với một số lý do nó chỉ không được giải quyết cho chuỗi nó đại diện.

Ngoài ra, nếu &amp; được sử dụng trong một phần tử, trình phân tích cú pháp sẽ giải quyết chính xác nó đến "&" và điều này được chuyển thành chuỗi khi phương thức ủy nhiệm parser:foundCharacters: được gọi.

+0

Tôi đang gặp sự cố này ngay bây giờ. Bạn đã giải quyết nó? –

+0

bạn có thể tìm thấy nó bằng [XPath] (http://en.wikipedia.org/wiki/XPath) không? –

+0

Tôi đã thực hiện truy vấn XPath trên 'my_element' và cả "foo" và "bar" cũng không được giải quyết. Có đúng để tham chiếu các thực thể được khai báo nội bộ như tôi đã làm không? –

Trả lời

2

tôi xem xét NSXMLParser.h trong đó liệt kê các phương pháp định nghĩa sau đây cho các đại biểu để hỗ trợ:

@interface NSObject (NSXMLParserDelegateEventAdditions) 
// Document handling methods 
- (void)parserDidStartDocument:(NSXMLParser *)parser; 
    // sent when the parser begins parsing of the document. 
- (void)parserDidEndDocument:(NSXMLParser *)parser; 
    // sent when the parser has completed parsing. If this is encountered, the parse was successful. 

// DTD handling methods for various declarations. 
- (void)parser:(NSXMLParser *)parser foundNotationDeclarationWithName:(NSString *)name publicID:(NSString *)publicID systemID:(NSString *)systemID; 

- (void)parser:(NSXMLParser *)parser foundUnparsedEntityDeclarationWithName:(NSString *)name publicID:(NSString *)publicID systemID:(NSString *)systemID notationName:(NSString *)notationName; 

- (void)parser:(NSXMLParser *)parser foundAttributeDeclarationWithName:(NSString *)attributeName forElement:(NSString *)elementName type:(NSString *)type defaultValue:(NSString *)defaultValue; 

- (void)parser:(NSXMLParser *)parser foundElementDeclarationWithName:(NSString *)elementName model:(NSString *)model; 

- (void)parser:(NSXMLParser *)parser foundInternalEntityDeclarationWithName:(NSString *)name value:(NSString *)value; 

- (void)parser:(NSXMLParser *)parser foundExternalEntityDeclarationWithName:(NSString *)name publicID:(NSString *)publicID systemID:(NSString *)systemID; 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict; 
    // sent when the parser finds an element start tag. 
    // In the case of the cvslog tag, the following is what the delegate receives: 
    // elementName == cvslog, namespaceURI == http://xml.apple.com/cvslog, qualifiedName == cvslog 
    // In the case of the radar tag, the following is what's passed in: 
    // elementName == radar, namespaceURI == http://xml.apple.com/radar, qualifiedName == radar:radar 
    // If namespace processing >isn't< on, the xmlns:radar="http://xml.apple.com/radar" is returned as an attribute pair, the elementName is 'radar:radar' and there is no qualifiedName. 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName; 
    // sent when an end tag is encountered. The various parameters are supplied as above. 

- (void)parser:(NSXMLParser *)parser didStartMappingPrefix:(NSString *)prefix toURI:(NSString *)namespaceURI; 
    // sent when the parser first sees a namespace attribute. 
    // In the case of the cvslog tag, before the didStartElement:, you'd get one of these with prefix == @"" and namespaceURI == @"http://xml.apple.com/cvslog" (i.e. the default namespace) 
    // In the case of the radar:radar tag, before the didStartElement: you'd get one of these with prefix == @"radar" and namespaceURI == @"http://xml.apple.com/radar" 

- (void)parser:(NSXMLParser *)parser didEndMappingPrefix:(NSString *)prefix; 
    // sent when the namespace prefix in question goes out of scope. 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string; 
    // This returns the string of the characters encountered thus far. You may not necessarily get the longest character run. The parser reserves the right to hand these to the delegate as potentially many calls in a row to -parser:foundCharacters: 

- (void)parser:(NSXMLParser *)parser foundIgnorableWhitespace:(NSString *)whitespaceString; 
    // The parser reports ignorable whitespace in the same way as characters it's found. 

- (void)parser:(NSXMLParser *)parser foundProcessingInstructionWithTarget:(NSString *)target data:(NSString *)data; 
    // The parser reports a processing instruction to you using this method. In the case above, target == @"xml-stylesheet" and data == @"type='text/css' href='cvslog.css'" 

- (void)parser:(NSXMLParser *)parser foundComment:(NSString *)comment; 
    // A comment (Text in a <!-- --> block) is reported to the delegate as a single string 

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock; 
    // this reports a CDATA block to the delegate as an NSData. 

- (NSData *)parser:(NSXMLParser *)parser resolveExternalEntityName:(NSString *)name systemID:(NSString *)systemID; 
    // this gives the delegate an opportunity to resolve an external entity itself and reply with the resulting data. 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError; 
    // ...and this reports a fatal error to the delegate. The parser will stop parsing. 

- (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError; 
    // If validation is on, this will report a fatal validation error to the delegate. The parser will stop parsing. 
@end 

Dựa vào thứ tự của các mục trong tập tin nó trông các phương pháp khai phát được dự kiến ​​sẽ xảy ra trước khi các yếu tố này tìm thấy (như bạn đã khám phá ra). Tôi sẽ thử xử lý tất cả các phương pháp này và xem liệu có bất kỳ phương pháp nào trong số chúng xảy ra hay không, nhưng tất cả chúng đều giống như chúng được thiết kế cho các mục đích sử dụng khác.

Tôi tự hỏi nếu có cách nào để gửi tất cả các tin nhắn chưa được gửi đến đại biểu của bạn chỉ trong trường hợp tài liệu/giao diện không đầy đủ.

+0

Tôi đã triển khai tất cả các đại biểu, theo đề xuất của bạn và chạy lại. Tuy nhiên, không có đại biểu được gọi khi phân tích cú pháp được "& my_symbol;".Như đã đề cập, việc xóa khai báo ENTITY sẽ gọi phương thức "resolveExternalEntityName", cho phép nó nhận ra nó là một tham chiếu thực thể. Đối với một số lý do, khi khai báo ENTITY có mặt (và được công nhận), nó chỉ không giải quyết tham chiếu đến giá trị của thực thể. –

+1

Theo dõi hy vọng của tôi rằng đó chỉ là một cuộc gọi phương thức không có giấy tờ, tôi đã tìm thấy trang này nói về cách tạo một đối tượng proxy. Có lẽ bạn có thể ném điều này trước mặt đại diện NSXMLParser của mình và tìm kiếm bất kỳ thứ gì không được xử lý: http://borkware.com/rants/agentm/elegant-delegation/ –

+0

Nhưng ngay cả khi nó trở thành thông báo không có giấy tờ bạn cần xử lý có vẻ như bạn sẽ cần báo cáo lỗi cho Apple. Hoặc nó cần phải được ghi lại hoặc cần phải được thực hiện và sau đó được ghi lại. –

Các vấn đề liên quan