- Inherits From:
- NSObject
- Conforms To:
- EDMLTagProcessor
- Declared In:
- EDAOMTagProcessor.h
The tag definition dictionary contains the elements' namespace (optional), the classes to be used for the document (optional), for text and for whitespace (optional) as well as the ones to be used for elements.
Text objects must implement the setText: method while Space objects may implement it to get the exact space string. (This also requires to set preservesWhitespace in the parser as otherwise the space string will always be @" "
.) All elements must implement takeValue:forAttribute: which is called once for each attribute and all container elements must implement setContainedObjects: which will be called after takeValue:forAttribute: to set the elements, and text/space objects, that were found between the start and end tags. The array is nil
if the element was empty.
Note that if acceptsUnknownTags is YES and multiple namespaces occur in the document takeValue:forAttribute: will be called for all attributes without indiciation of the attribute's namespace. Note also that if this is the case and additionally no namespace is defined for the elements, they will be asked to take values for attributes that correspond to the namespace definition, e.g. for the tag <mytag xmlns:t="...">
the element representing mytag
will be asked to take a value for the attribute t. The obvious workaround is to define a namespace for your elements; not a bad idea anyway when dealing with XML.
The namespace declaration in the tag definition must be a string stored under the key XMLNS
:
XMLNS = URI;
The class for document objects is defined as follows. Note that this is required only if the parseDocument: and/or parseXMLDocument: methods in the parser are used.
DOCUMENT = {
class = ClassName;
};
The classes for text and space are defined as follows:
"*" = {
class = ClassName;
};
"_" = {
class = ClassName;
};
Model classes for elements are defined in a similar way but have more parameters:
tag-name = {
class = ClassName;
container = YES or NO;
root = YES or NO;
required = ( attribute-name, attribute-name, ... );
optional = ( attribute-name, attribute-name, ... );
implicit = ( { attribute-name = value; } , { attribute-name = value; }, ... );
};
The root entry denotes whether the element can be a root element in a document. If a tag is parsed that does not have all attributes in required or it has attributes other than the ones listed in required and optional an exception is raised. The latter can be suppressed by using setIgnoresUnknownAttributes: or setAcceptsUnknownAttributes: The implicit list allows to pass attributes to the objects in addition to the ones defined in the document. This can be used, for example, to turn br tags (for linebreaks) into a space object as in the example from the EDStyleSheet framework:
"_" = {
class = EDSLSpace;
};
br = {
class = EDSLSpace;
implicit = ( { text = "\012"; } );
};
Note that this results in takeValue:@"\012" forAttribute:@"text"
being called; not setText:@"\012"
.
The processor implements the EDTagProcessorProtocol as follows: It returns the namespace defined in the tag definition dictionary, or nil
if there is none, as defaultNamespace. If a space object was defined it returns NO in spaceIsString, otherwise it returns YES which will make the parser treat all space between tags as text. The remaining four methods to create text and space objects as well as elements simply instantiate a corresponding object, set all properties and return it to the parser.
A convenience method is provided to use the EDMLParser with this processor. This reduces the code required to set up a parser to:
NSDictionary *myTagDefinitions; // assume this exists
NSString *myDocument; // assume this exists
EDMLParser *parser;
NSArray *toplevelElements;
parser = [EDMLParser parserWithTagDefinitions:myTagDefinitions];
toplevelElements = [parser parseString:myDocument];
struct _EDATPFlags flags;
NSDictionary *tagDefinitions;
NSDictionary *textObjectDefinition;
NSDictionary *spaceObjectDefinition;
NSDictionary *documentObjectDefinition;
NSSet *rootElementClasses;
flags All instance variables are private. tagDefinitions textObjectDefinition spaceObjectDefinition documentObjectDefinition rootElementClasses
Creating default tag processorsConfiguring the tag processor
- - initWithTagDefinitions:
- - setIgnoresUnknownNamespaces:
- - ignoresUnknownNamespaces
- - setIgnoresUnknownTags:
- - ignoresUnknownTags
- - setIgnoresUnknownAttributes:
- - ignoresUnknownAttributes
- - setAcceptsUnknownAttributes:
- - acceptsUnknownAttributes
- (BOOL)acceptsUnknownAttributes
Returns whether the processor accepts unknown attributes. See setAcceptsUnknownAttributes: for details.
- (BOOL)ignoresUnknownAttributes
Returns whether the processor ignores unknown attributes. See setIgnoresUnknownAttributes: for details.
- (BOOL)ignoresUnknownNamespaces
Returns whether the processor ignores unknown namespaces. See setIgnoresUnknownNamespaces: for details.
- (BOOL)ignoresUnknownTags
Returns whether the processor ignores unknown tags. See setIgnoresUnknownTags: for details.
- (id)initWithTagDefinitions:(NSDictionary *)someTagDefinitions
Initialises a newly allocated tag processor by setting the tag definitions to someTagDefinitions.
- (void)setAcceptsUnknownAttributes:(BOOL)flag
Controls unknown attribute handling. If set to NO the tag processor raises an exception whenever it encounters an unknown attribute from the namespace defined in the tag definitions. (Unless ignoresUnknownAttributes is set to YES.) If it encounters an attribute from a different namespace, behaviour depends on the ignoresUnknownNamespaces setting.
If set to YES, the processor calls takeValue:forAttribute: for unknown attributes, from all namespaces. Note that there is an interdependency with the ignoresUnknownAttributes setting as not both can be set to YES at the same time and the other is automatically reset if this one is set.
The default is not to accept unknown attributes.
- (void)setIgnoresUnknownAttributes:(BOOL)flag
Controls unknown attribute handling. If set to NO the tag processor raises an exception whenever it encounters an unknown attribute from the namespace defined in the tag definitions. (Unless acceptsUnknownAttributes is set to YES.) If it encounters an attribute from a different namespace, behaviour depends on the ignoresUnknownNamespaces setting.
If set to YES, the processor ignores the attribute, i.e. takeValue:forAttribute: is not called for these. Note that there is an interdependency with the acceptsUnknownAttributes setting as not both can be set to YES at the same time and the other is automatically reset if this one is set.
The default is not to ignore unknown attributes.
- (void)setIgnoresUnknownNamespaces:(BOOL)flag
Controls unknown namespace handling. If set to NO the tag processor raises an exception whenever it encounters a tag or an attribute from a namespace that is different from the namespace defined in the tag definitions.
If set to YES, the processor returns EDMLUnknownTag
to the parser which results in the tag to treated as a string. (See EDMLTagProcessorProtocol for more details.) Attributes from unknown namespace are simply ignored, i.e. takeValue:forAttribute: is not called for these.
The default is not to ignore unknown namespaces.
- (void)setIgnoresUnknownTags:(BOOL)flag
Controls unknown tag handling. If set to NO the tag processor raises an exception whenever it encounters an unknown tag from the namespace defined in the tag definitions. If it encounters a tag from a different namespace, behaviour depends on the ignoresUnknownNamespaces setting.
If set to YES, the processor returns, regardless of the tag's namespace, EDMLUnknownTag
to the parser which results in the tag to treated as a string. (See EDMLTagProcessorProtocol for more details.)
The default is not to ignore unknown tags.