/* * Copyright (c) 2008, 2009, 2010, 2011 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" #import "OFString.h" #import "OFXMLAttribute.h" @class OFXMLParser; @class OFArray; @class OFMutableArray; @class OFStream; #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) typedef void (^of_xml_parser_processing_instructions_block_t)( OFXMLParser *parser, OFString *pi); typedef void (^of_xml_parser_element_start_block_t)(OFXMLParser *parser, OFString *name, OFString *prefix, OFString *ns, OFArray *attributes); typedef void (^of_xml_parser_element_end_block_t)(OFXMLParser *parser, OFString *name, OFString *prefix, OFString *ns); typedef void (^of_xml_parser_string_block_t)(OFXMLParser *parser, OFString *string); typedef OFString* (^of_xml_parser_unknown_entity_block_t)(OFXMLParser *parser, OFString *entity); #endif /** * \brief A protocol that needs to be implemented by delegates for OFXMLParser. */ #ifndef OF_XML_PARSER_M @protocol OFXMLParserDelegate <OFObject> #else @protocol OFXMLParserDelegate #endif #ifdef OF_HAVE_OPTIONAL_PROTOCOLS @optional #endif /** * This callback is called when the XML parser found processing instructions. * * \param parser The parser which found processing instructions * \param pi The processing instructions */ - (void)parser: (OFXMLParser*)parser foundProcessingInstructions: (OFString*)pi; /** * This callback is called when the XML parser found the start of a new tag. * * \param parser The parser which found a new tag * \param name The name of the tag which just started * \param prefix The prefix of the tag which just started or nil * \param ns The namespace of the tag which just started or nil * \param attributes The attributes included in the tag which just started or * nil */ - (void)parser: (OFXMLParser*)parser didStartElement: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns attributes: (OFArray*)attributes; /** * This callback is called when the XML parser found the end of a tag. * * \param parser The parser which found the end of a tag * \param name The name of the tag which just ended * \param prefix The prefix of the tag which just ended or nil * \param ns The namespace of the tag which just ended or nil */ - (void)parser: (OFXMLParser*)parser didEndElement: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns; /** * This callback is called when the XML parser found characters. * * In case there are comments or CDATA, it is possible that this callback is * called multiple times in a row. * * \param parser The parser which found a string * \param characters The characters the XML parser found */ - (void)parser: (OFXMLParser*)parser foundCharacters: (OFString*)characters; /** * This callback is called when the XML parser found CDATA. * * \param parser The parser which found a string * \param CDATA The CDATA the XML parser found */ - (void)parser: (OFXMLParser*)parser foundCDATA: (OFString*)CDATA; /** * This callback is called when the XML parser found a comment. * * \param parser The parser which found a comment * \param comment The comment the XML parser found */ - (void)parser: (OFXMLParser*)parser foundComment: (OFString*)comment; /** * This callback is called when the XML parser found an entity it doesn't know. * The callback is supposed to return a substitution for the entity or nil if * it is not known to the callback as well, in which case an exception will be * risen. * * \param parser The parser which found an unknown entity * \param entity The name of the entity the XML parser didn't know * \return A substitution for the entity or nil */ - (OFString*)parser: (OFXMLParser*)parser foundUnknownEntityNamed: (OFString*)entity; @end /** * \brief An event-based XML parser. * * OFXMLParser is an event-based XML parser which calls the delegate's callbacks * as soon asit finds something, thus suitable for streams as well. */ @interface OFXMLParser: OFObject <OFStringXMLUnescapingDelegate> { id <OFXMLParserDelegate> delegate; enum { OF_XMLPARSER_OUTSIDE_TAG, OF_XMLPARSER_TAG_OPENED, OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS, OF_XMLPARSER_IN_TAG_NAME, OF_XMLPARSER_IN_CLOSE_TAG_NAME, OF_XMLPARSER_IN_TAG, OF_XMLPARSER_IN_ATTR_NAME, OF_XMLPARSER_EXPECT_DELIM, OF_XMLPARSER_IN_ATTR_VALUE, OF_XMLPARSER_EXPECT_CLOSE, OF_XMLPARSER_EXPECT_SPACE_OR_CLOSE, OF_XMLPARSER_IN_EXCLAMATIONMARK, OF_XMLPARSER_IN_CDATA_OPENING, OF_XMLPARSER_IN_CDATA_1, OF_XMLPARSER_IN_CDATA_2, OF_XMLPARSER_IN_COMMENT_OPENING, OF_XMLPARSER_IN_COMMENT_1, OF_XMLPARSER_IN_COMMENT_2, OF_XMLPARSER_IN_DOCTYPE, OF_XMLPARSER_NUM_STATES } state; OFMutableString *cache; OFString *name; OFString *prefix; OFMutableArray *namespaces; OFMutableArray *attributes; OFString *attributeName; OFString *attributePrefix; char delimiter; OFMutableArray *previous; #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) of_xml_parser_processing_instructions_block_t processingInstructionsHandler; of_xml_parser_element_start_block_t elementStartHandler; of_xml_parser_element_end_block_t elementEndHandler; of_xml_parser_string_block_t charactersHandler; of_xml_parser_string_block_t CDATAHandler; of_xml_parser_string_block_t commentHandler; of_xml_parser_unknown_entity_block_t unknownEntityHandler; #endif size_t level; BOOL acceptProlog; size_t lineNumber; BOOL lastCarriageReturn; BOOL finishedParsing; of_string_encoding_t encoding; } #ifdef OF_HAVE_PROPERTIES @property (retain) id <OFXMLParserDelegate> delegate; # ifdef OF_HAVE_BLOCKS @property (retain) of_xml_parser_processing_instructions_block_t processingInstructionsHandler; @property (retain) of_xml_parser_element_start_block_t elementStartHandler; @property (retain) of_xml_parser_element_end_block_t elementEndHandler; @property (retain) of_xml_parser_string_block_t charactersHandler; @property (retain) of_xml_parser_string_block_t CDATAHandler; @property (retain) of_xml_parser_string_block_t commentHandler; @property (retain) of_xml_parser_unknown_entity_block_t unknownEntityHandler; # endif #endif /** * \return A new, autoreleased OFXMLParser */ + parser; /** * \return The delegate that is used by the XML parser */ - (id <OFXMLParserDelegate>)delegate; /** * Sets the delegate the OFXMLParser should use. * * \param delegate The delegate to use */ - (void)setDelegate: (id <OFXMLParserDelegate>)delegate; #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) /** * \return The processing instructions handler */ - (of_xml_parser_processing_instructions_block_t)processingInstructionsHandler; /** * Sets the processing instructions handler. * * \param block A processing instructions handler */ - (void)setProcessingInstructionsHandler: (of_xml_parser_processing_instructions_block_t)block; /** * \return The element start handler */ - (of_xml_parser_element_start_block_t)elementStartHandler; /** * Sets the element start handler. * * \param block An element start handler */ - (void)setElementStartHandler: (of_xml_parser_element_start_block_t)block; /** * \return The element end handler */ - (of_xml_parser_element_end_block_t)elementEndHandler; /** * Sets the element end handler. * * \param block An element end handler */ - (void)setElementEndHandler: (of_xml_parser_element_end_block_t)block; /** * \return The characters handler */ - (of_xml_parser_string_block_t)charactersHandler; /** * Sets the characters handler. * * \param block A characters handler */ - (void)setCharactersHandler: (of_xml_parser_string_block_t)block; /** * \return The CDATA handler */ - (of_xml_parser_string_block_t)CDATAHandler; /** * Sets the CDATA handler. * * \param block A CDATA handler */ - (void)setCDATAHandler: (of_xml_parser_string_block_t)block; /** * \return The comment handler */ - (of_xml_parser_string_block_t)commentHandler; /** * Sets the comment handler. * * \param block A comment handler */ - (void)setCommentHandler: (of_xml_parser_string_block_t)block; /** * \return The unknown entity handler */ - (of_xml_parser_unknown_entity_block_t)unknownEntityHandler; /** * Sets the unknown entity handler. * * \param block An unknown entity handler */ - (void)setUnknownEntityHandler: (of_xml_parser_unknown_entity_block_t)block; #endif /** * Parses a buffer with the specified size. * * \param buffer The buffer to parse * \param length The length of the buffer */ - (void)parseBuffer: (const char*)buffer withLength: (size_t)length; /** * Parses the specified string. * * \param string The string to parse */ - (void)parseString: (OFString*)string; /** * Parses the specified stream. * * \param stream The stream to parse */ - (void)parseStream: (OFStream*)stream; /** * Parses the specified file. * * \param path The path to the file to parse */ - (void)parseFile: (OFString*)path; /** * \return The current line number */ - (size_t)lineNumber; /** * \return Whether the XML parser has finished parsing */ - (BOOL)finishedParsing; @end @interface OFObject (OFXMLParserDelegate) <OFXMLParserDelegate> @end