2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "libxmlSAXDriver.h"
24 #include "libxmlSAXLocator.h"
25 #include "TableCallbacks.h"
26 #include <SaxObjC/SaxException.h>
27 #include <SaxObjC/SaxAttributes.h>
30 #include <libxml/parser.h>
33 TODO: xmlChar is really UTF-8, not cString !!!
36 static NSString *SaxDeclHandlerProperty =
37 @"http://xml.org/sax/properties/declaration-handler";
38 static NSString *SaxLexicalHandlerProperty =
39 @"http://xml.org/sax/properties/lexical-handler";
41 static NSString *SaxDOMNodeProperty =
42 @"http://xml.org/sax/properties/dom-node";
43 static NSString *SaxXMLStringProperty =
44 @"http://xml.org/sax/properties/xml-string";
47 static int _UTF8ToUTF16(unsigned char **sourceStart, unsigned char *sourceEnd,
48 unichar **targetStart, const unichar *targetEnd);
50 static NSMapTable *uniqueStrings = NULL; // THREAD
51 static Class NSStringClass = Nil;
53 static inline NSString *xmlCharsToString(const xmlChar *_s) {
57 if (_s == NULL) return nil;
59 if (uniqueStrings == NULL) {
60 uniqueStrings = NSCreateMapTable(libxmlNonOwnedCStringMapKeyCallBacks,
61 NSObjectMapValueCallBacks,
64 else if ((s = NSMapGet(uniqueStrings, _s))) {
65 /* found a string in cache ... */
69 newkey = malloc(strlen(_s) + 1);
72 if (NSStringClass == Nil)
73 NSStringClass = [NSString class];
75 s = [[NSStringClass alloc] initWithUTF8String:_s];
76 NSMapInsert(uniqueStrings, newkey, s);
80 extern xmlParserCtxtPtr xmlCreateMemoryParserCtxt(char *buffer, int size);
82 @implementation libxmlSAXDriver
84 static libxmlSAXDriver *activeDriver = nil;
87 _startElement(libxmlSAXDriver *self, const xmlChar *name, const xmlChar **atts);
88 static void _endElement(libxmlSAXDriver *self, const xmlChar *name);
89 static void _startDocument(libxmlSAXDriver *self);
90 static void _endDocument(libxmlSAXDriver *self);
91 static void _characters(libxmlSAXDriver *self, const xmlChar *chars, int len);
93 _ignorableWhiteSpace(libxmlSAXDriver *self, const xmlChar *chars, int len);
94 static void __pi(libxmlSAXDriver *self, const xmlChar *target, const xmlChar *data);
95 static void _comment(libxmlSAXDriver *self, const xmlChar *value);
96 static xmlParserInputPtr
97 _resolveEntity(libxmlSAXDriver *self, const xmlChar *pub, const xmlChar *sys)
98 __attribute__((unused));
99 static xmlEntityPtr _getEntity(libxmlSAXDriver *self, const xmlChar *name)
100 __attribute__((unused));
101 static void _warning(libxmlSAXDriver *self, const char *msg, ...);
102 static void _error(libxmlSAXDriver *self, const char *msg, ...);
103 static void _fatalError(libxmlSAXDriver *self, const char *msg, ...);
104 static void _setLocator(void *udata, xmlSAXLocatorPtr _locator);
105 static void _cdataBlock(libxmlSAXDriver *self, const xmlChar *value, int len);
106 static void _entityDecl(libxmlSAXDriver *self, const xmlChar *name, int type,
107 const xmlChar *publicId, const xmlChar *systemId,
109 __attribute__((unused));
110 static void _notationDecl(libxmlSAXDriver *self, const xmlChar *name,
111 const xmlChar *publicId, const xmlChar *systemId)
112 __attribute__((unused));
114 _unparsedEntityDecl(libxmlSAXDriver *self, const xmlChar *name,
115 const xmlChar *publicId, const xmlChar *systemId,
116 const xmlChar *notationName)
117 __attribute__((unused));
118 static void _elementDecl(libxmlSAXDriver *self, const xmlChar *name, int type,
119 xmlElementContentPtr content)
120 __attribute__((unused));
121 static void _attrDecl(libxmlSAXDriver *self, const xmlChar *elem,
122 const xmlChar *name, int type, int def,
123 const xmlChar *defaultValue, xmlEnumerationPtr tree)
124 __attribute__((unused));
125 static void _internalSubset(libxmlSAXDriver *ctx, const xmlChar *name,
126 const xmlChar *ExternalID, const xmlChar *SystemID);
127 static void _externalSubset(libxmlSAXDriver *ctx, const xmlChar *name,
128 const xmlChar *ExternalID, const xmlChar *SystemID);
129 static void _reference(libxmlSAXDriver *ctx, const xmlChar *name);
131 static int _isStandalone(libxmlSAXDriver *self);
132 static int _hasInternalSubset(libxmlSAXDriver *self);
133 static int _hasExternalSubset(libxmlSAXDriver *self);
136 static xmlSAXHandler saxHandler = {
137 (void*)_internalSubset, /* internalSubset */
141 (void*)_isStandalone, /* isStandalone */
142 (void*)_hasInternalSubset, /* hasInternalSubset */
143 (void*)_hasExternalSubset, /* hasExternalSubset */
145 #if HANDLE_XML_ENTITIES
146 (void*)_resolveEntity, /* resolveEntity */
147 (void*)_getEntity, /* getEntity */
152 (void*)_entityDecl, /* entityDecl */
153 (void*)_notationDecl, /* notationDecl */
154 (void*)_attrDecl, /* attributeDecl */
155 (void*)_elementDecl, /* elementDecl */
156 (void*)_unparsedEntityDecl, /* unparsedEntityDecl */
158 NULL, NULL, NULL, NULL, NULL,
160 (void*)_setLocator, /* setDocumentLocator */
161 (void*)_startDocument, /* startDocument */
162 (void*)_endDocument, /* endDocument */
163 (void*)_startElement, /* startElement */
164 (void*)_endElement, /* endElement */
165 (void*)_reference, /* reference */
166 (void*)_characters, /* characters */
167 (void*)_ignorableWhiteSpace, /* ignorableWhitespace */
168 (void*)__pi, /* processingInstruction */
169 (void*)_comment, /* comment */
170 (void*)_warning, /* warning */
171 (void*)_error, /* error */
172 (void*)_fatalError, /* fatalError */
173 NULL, /* getParameterEntity */
174 (void*)_cdataBlock, /* cdataBlock */
175 (void*)_externalSubset /* externalSubset */
179 self->sax = &saxHandler;
180 self->nsStack = [[NSMutableArray alloc] init];
182 /* feature defaults */
183 self->fNamespaces = YES;
184 self->fNamespacePrefixes = NO;
190 [self->attrs release];
191 [self->nsStack release];
193 [self->declHandler release];
194 [self->lexicalHandler release];
195 [self->contentHandler release];
196 [self->dtdHandler release];
197 [self->errorHandler release];
198 [self->entityResolver release];
200 [self->locator clear];
201 [self->locator release];
203 if (self->entity) free(self->entity);
209 - (void)setProperty:(NSString *)_name to:(id)_value {
210 if ([_name isEqualToString:SaxLexicalHandlerProperty]) {
211 ASSIGN(self->lexicalHandler, _value);
214 if ([_name isEqualToString:SaxDeclHandlerProperty]) {
215 ASSIGN(self->declHandler, _value);
219 [SaxNotRecognizedException raise:@"PropertyException"
220 format:@"don't know property %@", _name];
222 - (id)property:(NSString *)_name {
223 if ([_name isEqualToString:SaxLexicalHandlerProperty])
224 return self->lexicalHandler;
225 if ([_name isEqualToString:SaxDeclHandlerProperty])
226 return self->declHandler;
228 [SaxNotRecognizedException raise:@"PropertyException"
229 format:@"don't know property %@", _name];
235 - (void)setFeature:(NSString *)_name to:(BOOL)_value {
236 if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) {
237 self->fNamespaces = _value;
241 if ([_name isEqualToString:
242 @"http://xml.org/sax/features/namespace-prefixes"]) {
243 self->fNamespacePrefixes = _value;
247 [SaxNotRecognizedException raise:@"FeatureException"
248 format:@"don't know feature %@", _name];
250 - (BOOL)feature:(NSString *)_name {
251 if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"])
252 return self->fNamespaces;
254 if ([_name isEqualToString:
255 @"http://xml.org/sax/features/namespace-prefixes"])
256 return self->fNamespacePrefixes;
258 if ([_name isEqualToString:
259 @"http://www.skyrix.com/sax/features/predefined-namespaces"])
262 [SaxNotRecognizedException raise:@"FeatureException"
263 format:@"don't know feature %@", _name];
269 - (void)setDTDHandler:(id<NSObject,SaxDTDHandler>)_handler {
270 ASSIGN(self->dtdHandler, _handler);
272 - (id<NSObject,SaxDTDHandler>)dtdHandler {
273 return self->dtdHandler;
276 - (void)setErrorHandler:(id<NSObject,SaxErrorHandler>)_handler {
277 ASSIGN(self->errorHandler, _handler);
279 - (id<NSObject,SaxErrorHandler>)errorHandler {
280 return self->errorHandler;
283 - (void)setEntityResolver:(id<NSObject,SaxEntityResolver>)_handler {
284 ASSIGN(self->entityResolver, _handler);
286 - (id<NSObject,SaxEntityResolver>)entityResolver {
287 return self->entityResolver;
290 - (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler {
291 ASSIGN(self->contentHandler, _handler);
293 - (id<NSObject,SaxContentHandler>)contentHandler {
294 return self->contentHandler;
299 - (NSStringEncoding)encodingForXMLEncodingString:(NSString *)_enc {
300 // TODO: use the string-charset functions in NGExtensions
301 _enc = [_enc lowercaseString];
303 if ([_enc isEqualToString:@"utf-8"])
304 return NSUTF8StringEncoding;
305 if ([_enc isEqualToString:@"iso-8859-1"])
306 return NSISOLatin1StringEncoding;
308 #ifndef NeXT_Foundation_LIBRARY
309 if ([_enc isEqualToString:@"iso-8859-9"])
310 return NSISOLatin9StringEncoding;
313 if ([_enc isEqualToString:@"iso-8859-2"])
314 return NSISOLatin2StringEncoding;
316 if ([_enc isEqualToString:@"ascii"])
317 return NSASCIIStringEncoding;
319 NSLog(@"%s: UNKNOWN XML ENCODING '%@'",
320 __PRETTY_FUNCTION__, _enc);
323 - (NSData *)dataForXMLString:(NSString *)_string {
329 r = [_string rangeOfString:@"?>"];
330 if ([_string hasPrefix:@"<?xml "] && (r.length != 0)) {
333 xmlDecl = [_string substringToIndex:r.location];
335 r = [xmlDecl rangeOfString:@"encoding='"];
337 xmlDecl = [_string substringFromIndex:(r.location + 10)];
338 r = [xmlDecl rangeOfString:@"'"];
339 xmlDecl = (r.length > 0)
340 ? [xmlDecl substringToIndex:r.location]
344 r = [xmlDecl rangeOfString:@"encoding=\""];
346 xmlDecl = [_string substringFromIndex:(r.location + r.length)];
347 r = [xmlDecl rangeOfString:@"\""];
348 xmlDecl = r.length > 0
349 ? [xmlDecl substringToIndex:r.location]
356 if ([xmlDecl length] > 0) {
357 NSStringEncoding enc;
359 if ((enc = [self encodingForXMLEncodingString:xmlDecl]) != 0) {
360 data = [_string dataUsingEncoding:enc];
362 NSLog(@"WARNING(%s): couldn't get data for string '%@', "
363 @"encoding %i !", __PRETTY_FUNCTION__, _string, enc);
371 data = [_string dataUsingEncoding:NSUTF8StringEncoding];
376 - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId {
377 NSAutoreleasePool *pool;
379 if (_source == nil) {
384 if ([_source isKindOfClass:[NSString class]]) {
385 /* convert strings to UTF8 data */
386 if (_sysId == nil) _sysId = @"<string>";
387 _source = [self dataForXMLString:_source];
389 else if ([_source isKindOfClass:[NSURL class]]) {
390 if (_sysId == nil) _sysId = [_source absoluteString];
391 _source = [_source resourceDataUsingCache:NO];
393 else if ([_source isKindOfClass:[NSData class]]) {
394 if (_sysId == nil) _sysId = @"<data>";
397 SaxParseException *e;
400 ui = [NSDictionary dictionaryWithObjectsAndKeys:
401 _source ? _source : @"<nil>", @"source",
405 e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
406 reason:@"can't handle data-source"
409 [self->errorHandler fatalError:e];
413 pool = [[NSAutoreleasePool alloc] init];
417 unsigned char *src, *start;
421 if ((len = [_source length]) == 0) {
426 /* zero-terminate the data !!! */
427 src = malloc(len + 1);
428 [_source getBytes:src length:len];
435 if ((tmp = strstr(src, "<?xml"))) {
437 /* skip leading spaces till <?xml ...*/
438 while (*start != '\0' && isspace(*start)) {
446 if (activeDriver != nil) {
447 NSLog(@"ERROR(%s): %@ there is an active driver set (%@), override !",
448 __PRETTY_FUNCTION__, self, activeDriver);
453 xmlCreateMemoryParserCtxt(start, len);
455 if (self->ctxt == nil) {
456 SaxParseException *e;
459 NSLog(@"%s: couldn't create memory parser ctx (src=0x%08X, len=%d) !",
460 __PRETTY_FUNCTION__, src, len);
462 if (activeDriver == self)
466 e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
467 reason:@"couldn't create memory parser context"
470 [self->errorHandler fatalError:e];
474 if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) {
475 ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename =
479 oldsax = ((xmlParserCtxtPtr)self->ctxt)->sax;
480 ((xmlParserCtxtPtr)self->ctxt)->sax = self->sax;
481 ((xmlParserCtxtPtr)self->ctxt)->userData = self;
483 xmlParseDocument(ctxt);
485 if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed))
486 NSLog(@"%@: not well formed", _sysId);
488 if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0)
489 ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename =NULL;
491 ((xmlParserCtxtPtr)self->ctxt)->sax = oldsax;
492 ((xmlParserCtxtPtr)self->ctxt)->userData = NULL;
493 xmlFreeParserCtxt(ctxt);
495 if (activeDriver == self)
506 - (void)parseFromSource:(id)_source {
507 [self parseFromSource:_source systemId:nil];
510 static int mfread(void *f, char *buf, int len) {
512 l = fread(buf, 1, len, f);
513 //printf("read %i bytes\n", l);
516 static int mfclose(void *f) {
520 - (void)parseFromSystemId:(NSString *)_sysId {
521 /* _sysId is a URI */
522 NSAutoreleasePool *pool;
524 if (![_sysId hasPrefix:@"file:"]) {
525 SaxParseException *e;
529 if ((url = [NSURL URLWithString:_sysId])) {
530 [self parseFromSource:url systemId:_sysId];
534 ui = [NSDictionary dictionaryWithObjectsAndKeys:
535 _sysId ? _sysId : @"<nil>", @"systemID",
539 e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
540 reason:@"can't handle system-id"
543 [self->errorHandler fatalError:e];
547 pool = [[NSAutoreleasePool alloc] init];
549 /* cut off file:// */
550 if ([_sysId hasPrefix:@"file://"])
551 _sysId = [_sysId substringFromIndex:7];
553 _sysId = [_sysId substringFromIndex:5];
555 /* start parsing .. */
557 ret = xmlSAXUserParseFile(self->sax, (void *)self, [_sysId cString]);
561 f = fopen([_sysId cString], "r");
564 SaxParseException *e;
567 NSLog(@"%s: missing file '%@'", __PRETTY_FUNCTION__, _sysId);
569 ui = [NSDictionary dictionaryWithObjectsAndKeys:
570 _sysId ? _sysId : @"<nil>", @"path",
573 e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
574 reason:@"can't find file"
577 [self->errorHandler fatalError:e];
583 xmlCreateIOParserCtxt(self->sax, self /* userdata */,
585 mfclose, /* ioclose */
587 XML_CHAR_ENCODING_UTF8 /* encoding */);
589 if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) {
590 ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename =
594 if (activeDriver != nil) {
595 NSLog(@"WARNING(%s): %@ there is an active driver set (%@), override !",
596 __PRETTY_FUNCTION__, self, activeDriver);
600 xmlParseDocument(self->ctxt);
602 if (activeDriver == self)
605 if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0)
606 ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename =NULL;
608 if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed))
609 NSLog(@"%@: not well formed", _sysId);
611 ((xmlParserCtxtPtr)self->ctxt)->sax = NULL;
612 xmlFreeParserCtxt(self->ctxt);
621 - (NSString *)replacementStringForEntityNamed:(NSString *)_entityName {
622 // TODO: check, how this is used, could explain some problems
623 //NSLog(@"get entity: %@", _entityName);
624 return [[@"&" stringByAppendingString:_entityName]
625 stringByAppendingString:@";"];
628 /* namespace support */
630 - (NSString *)nsUriForPrefix:(NSString *)_prefix {
634 e = [self->nsStack reverseObjectEnumerator];
635 while ((ns = [e nextObject])) {
638 if ((uri = [ns objectForKey:_prefix])) {
639 //NSLog(@"prefix %@ -> uri %@", _prefix, uri);
643 //NSLog(@"prefix %@ -> uri %@", _prefix, nil);
647 - (NSString *)defaultNamespace {
648 return [self nsUriForPrefix:@":"];
651 - (void)declarePrefix:(NSString *)_prefix namespaceURI:(NSString *)_uri {
652 NSMutableDictionary *ns = nil;
656 NSCAssert(self->nsStack, @"missing namespace stack");
658 if ((count = [self->nsStack count]) == 0)
659 ns = [[NSMutableDictionary alloc] initWithCapacity:2];
661 ns = [[self->nsStack lastObject] mutableCopy];
663 if ([_prefix length] == 0)
666 [ns setObject:_uri forKey:_prefix];
672 [self->nsStack addObject:newns];
674 [self->nsStack replaceObjectAtIndex:(count - 1) withObject:newns];
679 /* ---------- libxml sax connection ---------- */
682 _startElement(libxmlSAXDriver *self, const xmlChar *name, const xmlChar **atts)
684 NSString *ename, *rawName, *euri;
685 NSDictionary *nsDict = nil;
688 /* first scan for namespace declaration */
691 NSMutableDictionary *ns = nil;
694 for (i = 0; atts[i]; i += 2) {
695 const xmlChar *an = atts[i];
697 /* check for attr-names beginning with 'xmlns' */
698 if (an[0] != 'x') continue;
699 if (an[1] != 'm') continue;
700 if (an[2] != 'l') continue;
701 if (an[3] != 'n') continue;
702 if (an[4] != 's') continue;
704 /* ok, found ns decl */
706 if (ns == nil) ns = [[NSMutableDictionary alloc] init];
709 /* eg <x xmlns:nl="http://www.w3.org"/> */
710 NSString *prefix, *uri;
713 /* invalid, namespace name may not be empty ! */
714 NSLog(@"WARNING(%s): empty namespace prefix !", __PRETTY_FUNCTION__);
717 prefix = xmlCharsToString(&(an[6]));
718 uri = xmlCharsToString(atts[i + 1]);
720 //NSLog(@"prefix %@ uri %@", prefix, uri);
722 NSCAssert(ns, @"missing namespace dictionary");
723 [ns setObject:uri forKey:prefix];
725 if (self->fNamespaces)
726 [self->contentHandler startPrefixMapping:prefix uri:uri];
728 [prefix release]; prefix = nil;
729 [uri release]; uri = nil;
732 /* eg <x xmlns="http://www.w3.org"/> */
735 uri = xmlCharsToString(atts[i + 1]);
736 [ns setObject:uri forKey:@":"];
738 //NSLog(@"prefix default uri %@", uri);
739 [uri release]; uri = nil;
747 /* manage namespace stack */
750 nsDict = [NSDictionary dictionary];
752 NSCAssert(self->nsStack, @"missing namespace stack");
753 [self->nsStack addObject:nsDict];
755 /* process element name */
757 rawName = xmlCharsToString(name);
758 r = [rawName rangeOfString:@":"];
760 /* eg: <edi:bill/> */
763 prefix = [rawName substringToIndex:r.location];
764 ename = [rawName substringFromIndex:(r.location + r.length)];
765 euri = [self nsUriForPrefix:prefix];
769 euri = [self defaultNamespace];
772 /* create sax attrs */
774 if (self->attrs == nil)
775 self->attrs = [[SaxAttributes alloc] init];
782 for (i = 0; atts[i]; i += 2) {
783 NSString *name, *rawName, *uri;
784 NSString *type, *value;
787 if (!self->fNamespacePrefixes) {
788 if (atts[i][0] == 'x') {
789 const char *an = atts[i];
791 if (strstr(an, "xmlns") == an)
796 rawName = xmlCharsToString(atts[i]);
797 r = [rawName rangeOfString:@":"];
800 /* explicit attribute namespace, eg '<d edi:bill="100"/>' */
803 prefix = [rawName substringToIndex:r.location];
804 name = [rawName substringFromIndex:(r.location + r.length)];
805 uri = [self nsUriForPrefix:prefix];
808 /* plain attribute, eg '<d bill="100"/>' */
810 uri = euri; /* attr inherits namespace from element-name */
814 value = xmlCharsToString(atts[i + 1]);
817 addAttribute:name uri:uri rawName:rawName
818 type:type value:value];
820 [value release]; value = nil;
821 [rawName release]; rawName = nil;
827 /* send notification */
829 [self->contentHandler startElement:ename namespace:euri
831 attributes:self->attrs];
833 [rawName release]; rawName = nil;
838 static void _endElement(libxmlSAXDriver *self, const xmlChar *name) {
839 NSString *ename, *rawName, *uri;
842 rawName = xmlCharsToString(name);
843 r = [rawName rangeOfString:@":"];
846 /* eg: <edi:bill/> */
849 prefix = [rawName substringToIndex:r.location];
850 ename = [rawName substringFromIndex:(r.location + r.length)];
851 uri = [self nsUriForPrefix:prefix];
855 uri = [self defaultNamespace];
858 [self->contentHandler endElement:ename namespace:uri rawName:rawName];
860 [rawName release]; rawName = nil;
862 /* process namespace stack */
864 if (self->fNamespaces) {
869 ns = [self->nsStack lastObject];
870 keys = [ns keyEnumerator];
871 while ((key = [keys nextObject])) {
872 if ([key isEqualToString:@":"])
874 [self->contentHandler endPrefixMapping:key];
877 [self->nsStack removeLastObject];
880 static void _startDocument(libxmlSAXDriver *self) {
881 static NSDictionary *defNS = nil;
882 id keys[2], values[2];
884 //NSLog(@"start doc 0x%08X", self);
887 keys[0] = @"xml"; values[0] = @"http://www.w3.org/XML/1998/namespace";
888 keys[1] = @":"; values[1] = @"";
889 defNS = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:2];
891 if ([self->nsStack count] == 0)
892 [self->nsStack addObject:defNS];
894 [self->nsStack insertObject:defNS atIndex:0];
896 [self->contentHandler startDocument];
898 static void _endDocument(libxmlSAXDriver *self) {
899 [self->contentHandler endDocument];
901 if ([self->nsStack count] > 0)
902 [self->nsStack removeObjectAtIndex:0];
904 NSLog(@"libxmlSAXDriver: inconsistent state, "
905 @"nothing on NS stack in endDocument !");
909 static void _characters(libxmlSAXDriver *self, const xmlChar *chars, int len) {
910 /* need to transform UTF8 to UTF16 */
916 [self->contentHandler characters:data length:0];
920 [self->contentHandler characters:NULL length:0];
924 data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */
926 if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len),
927 (void *)&ts, ts + (len * sizeof(unichar)))) {
929 NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !",
930 __PRETTY_FUNCTION__, __LINE__);
933 [self->contentHandler characters:data length:((unsigned)(ts - data))];
939 _ignorableWhiteSpace(libxmlSAXDriver *self, const xmlChar *chars, int len)
941 /* need to transform UTF8 to UTF16 */
947 [self->contentHandler ignorableWhitespace:data length:len];
951 [self->contentHandler ignorableWhitespace:NULL length:0];
955 data = ts = calloc(len + 1, sizeof(unichar)); /* GC ?! */
957 if (_UTF8ToUTF16((void *)&chars, (void *)(chars + len),
958 (void *)&ts, ts + (len * sizeof(unichar)))) {
960 NSLog(@"ERROR(%s:%i): couldn't convert UTF8 to UTF16 !",
961 __PRETTY_FUNCTION__, __LINE__);
964 [self->contentHandler ignorableWhitespace:data length:(ts - data)];
969 static void __pi(libxmlSAXDriver *self, const xmlChar *pi, const xmlChar *data) {
970 NSString *epi, *edata;
972 epi = xmlCharsToString(pi);
973 edata = xmlCharsToString(data);
975 [self->contentHandler processingInstruction:epi data:edata];
977 [epi release]; epi = nil;
978 [edata release]; edata = nil;
981 static void _comment(libxmlSAXDriver *self, const xmlChar *value) {
982 if (self->lexicalHandler) {
983 /* need to transform UTF8 to UTF16 */
989 data = calloc(len +1 ,sizeof(unichar)); /* GC ?! */
991 for (i = 0; i < len; i++)
994 [self->lexicalHandler comment:data length:len];
996 if (data) { free(data); data = NULL; }
1000 static void _setLocator(void *udata, xmlSAXLocatorPtr _locator) {
1001 if (activeDriver == nil) {
1002 NSLog(@"ERROR(%s): no driver is active !", __PRETTY_FUNCTION__);
1006 [activeDriver->locator release];
1008 activeDriver->locator = [[libxmlSAXLocator alloc]
1009 initWithSaxLocator:_locator
1010 parser:activeDriver];
1011 activeDriver->locator->ctx = activeDriver->ctxt;
1013 [activeDriver->contentHandler setDocumentLocator:activeDriver->locator];
1016 static xmlParserInputPtr
1017 _resolveEntity(libxmlSAXDriver *self, const xmlChar *pub, const xmlChar *sys)
1019 NSString *pubId, *sysId;
1022 pubId = xmlCharsToString(pub);
1023 sysId = xmlCharsToString(sys);
1025 src = [self->entityResolver resolveEntityWithPublicId:pubId systemId:sysId];
1027 //return xmlLoadExternalEntity(sys, pub, self);
1031 NSLog(@"ignored entity src %@", src);
1033 [pubId release]; pubId = nil;
1034 [sysId release]; sysId = nil;
1038 static xmlEntityPtr _getEntity(libxmlSAXDriver *self, const xmlChar *name) {
1040 NSString *ename, *s;
1042 if ((p = xmlGetPredefinedEntity(name)))
1045 if (self->entity == NULL)
1046 /* setup shared entity structure */
1047 self->entity = calloc(1, sizeof(xmlEntity));
1049 ename = xmlCharsToString(name);
1050 s = [self replacementStringForEntityNamed:ename];
1052 /* need to convert to unicode ! */
1054 /* fill entity structure */
1056 p->name = [ename cString];
1057 p->etype = XML_INTERNAL_GENERAL_ENTITY;
1058 p->orig = (void *)[ename cString];
1059 p->content = (void *)[s cString];
1060 p->length = [s cStringLength];
1062 [ename release]; ename = nil;
1067 static void _cdataBlock(libxmlSAXDriver *self, const xmlChar *value, int len) {
1068 [self->lexicalHandler startCDATA];
1069 _characters(self, value, len);
1070 [self->lexicalHandler endCDATA];
1073 static SaxParseException *
1074 mkException(libxmlSAXDriver *self, NSString *key, const char *msg, va_list va)
1076 NSString *s, *reason;
1078 SaxParseException *e;
1081 id keys[7], values[7];
1084 s = [NSString stringWithCString:msg];
1085 s = [[[NSString alloc]
1086 initWithFormat:s arguments:va]
1088 r = [s rangeOfString:@"\n"];
1089 reason = r.length > 0
1090 ? [s substringToIndex:r.location]
1093 if ([reason length] == 0)
1094 reason = @"unknown reason";
1096 keys[0] = @"parser"; values[0] = self; count++;
1097 keys[1] = @"depth"; values[1] = [NSNumber numberWithInt:self->depth]; count++;
1099 if ([s length] > 0) {
1100 keys[count] = @"errorMessage";
1105 if ((i = [self->locator lineNumber]) >= 0) {
1106 keys[count] = @"line";
1107 values[count] = [NSNumber numberWithInt:i];
1110 if ((i = [self->locator columnNumber]) >= 0) {
1111 keys[count] = @"column";
1112 values[count] = [NSNumber numberWithInt:i];
1115 if ((tmp = [self->locator publicId])) {
1116 keys[count] = @"publicId";
1117 values[count] = tmp;
1120 if ((tmp = [self->locator systemId])) {
1121 keys[count] = @"systemId";
1122 values[count] = tmp;
1126 ui = [NSDictionary dictionaryWithObjects:values forKeys:keys count:count];
1128 e = (id)[SaxParseException exceptionWithName:key
1134 static void _warning(libxmlSAXDriver *self, const char *msg, ...) {
1136 SaxParseException *e;
1138 va_start(args, msg);
1139 e = mkException(self, @"SAXWarning", msg, args);
1142 [self->errorHandler warning:e];
1144 static void _error(libxmlSAXDriver *self, const char *msg, ...) {
1146 SaxParseException *e;
1148 va_start(args, msg);
1149 e = mkException(self, @"SAXError", msg, args);
1152 [self->errorHandler error:e];
1154 static void _fatalError(libxmlSAXDriver *self, const char *msg, ...) {
1156 SaxParseException *e;
1158 va_start(args, msg);
1159 e = mkException(self, @"SAXFatalError", msg, args);
1162 [self->errorHandler fatalError:e];
1165 static void _entityDecl(libxmlSAXDriver *self, const xmlChar *name, int type,
1166 const xmlChar *publicId, const xmlChar *systemId,
1169 NSString *ename, *pubId, *sysId;
1172 ename = xmlCharsToString(name);
1173 pubId = xmlCharsToString(publicId);
1174 sysId = xmlCharsToString(systemId);
1175 value = xmlCharsToString(content);
1178 case XML_INTERNAL_GENERAL_ENTITY:
1179 case XML_INTERNAL_PARAMETER_ENTITY:
1180 case XML_INTERNAL_PREDEFINED_ENTITY:
1181 [self->declHandler internalEntityDeclaration:ename value:value];
1184 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1185 case XML_EXTERNAL_PARAMETER_ENTITY:
1186 [self->declHandler externalEntityDeclaration:ename
1187 publicId:pubId systemId:sysId];
1190 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1191 /* is content really =notationName ??? */
1192 NSLog(@"unparsed ext entity ..");
1193 [self->dtdHandler unparsedEntityDeclaration:ename
1194 publicId:pubId systemId:sysId
1195 notationName:value];
1199 [NSException raise:@"InvalidEntityType"
1200 format:@"don't know entity type with code %i", type];
1210 _unparsedEntityDecl(libxmlSAXDriver *self,const xmlChar *name,
1211 const xmlChar *publicId, const xmlChar *systemId,
1212 const xmlChar *notationName)
1214 if (self->dtdHandler) {
1215 NSString *ename, *nname, *pubId, *sysId;
1217 ename = xmlCharsToString(name);
1218 nname = xmlCharsToString(notationName);
1219 pubId = xmlCharsToString(publicId);
1220 sysId = xmlCharsToString(systemId);
1222 [self->dtdHandler unparsedEntityDeclaration:ename
1223 publicId:pubId systemId:sysId
1224 notationName:nname];
1233 static void _notationDecl(libxmlSAXDriver *self, const xmlChar *name,
1234 const xmlChar *publicId, const xmlChar *systemId)
1236 if (self->dtdHandler) {
1237 NSString *nname, *pubId, *sysId;
1239 nname = xmlCharsToString(name);
1240 pubId = xmlCharsToString(publicId);
1241 sysId = xmlCharsToString(systemId);
1243 [self->dtdHandler notationDeclaration:nname publicId:pubId systemId:sysId];
1251 static NSString *_occurString(xmlElementContentOccur _occurType)
1252 __attribute__((unused));
1253 static NSString *_occurString(xmlElementContentOccur _occurType) {
1254 switch (_occurType) {
1255 case XML_ELEMENT_CONTENT_ONCE: return @"";
1256 case XML_ELEMENT_CONTENT_OPT: return @"?";
1257 case XML_ELEMENT_CONTENT_MULT: return @"*";
1258 case XML_ELEMENT_CONTENT_PLUS: return @"+";
1263 static void _addElemModel(xmlElementContentPtr p, NSMutableString *s, int pt) {
1264 if (p == NULL) return;
1267 case XML_ELEMENT_CONTENT_PCDATA:
1268 if (pt == -1) [s appendString:@"("];
1269 [s appendString:@"#PCDATA"];
1270 if (pt == -1) [s appendString:@")"];
1273 case XML_ELEMENT_CONTENT_ELEMENT: {
1276 ename = xmlCharsToString(p->name);
1278 if (pt == -1) [s appendString:@"("];
1279 [s appendString:ename];
1280 if (pt == -1) [s appendString:@")"];
1282 [ename release]; ename = nil;
1286 case XML_ELEMENT_CONTENT_SEQ:
1287 if (pt != XML_ELEMENT_CONTENT_SEQ) [s appendString:@"("];
1288 _addElemModel(p->c1, s, XML_ELEMENT_CONTENT_SEQ);
1289 [s appendString:@","];
1290 _addElemModel(p->c2, s, XML_ELEMENT_CONTENT_SEQ);
1291 if (pt != XML_ELEMENT_CONTENT_SEQ) [s appendString:@")"];
1294 case XML_ELEMENT_CONTENT_OR:
1295 if (pt != XML_ELEMENT_CONTENT_OR) [s appendString:@"("];
1296 _addElemModel(p->c1, s, XML_ELEMENT_CONTENT_OR);
1297 [s appendString:@"|"];
1298 _addElemModel(p->c2, s, XML_ELEMENT_CONTENT_OR);
1299 if (pt != XML_ELEMENT_CONTENT_OR) [s appendString:@")"];
1303 case XML_ELEMENT_CONTENT_ONCE: break;
1304 case XML_ELEMENT_CONTENT_OPT: [s appendString:@"?"]; break;
1305 case XML_ELEMENT_CONTENT_MULT: [s appendString:@"*"]; break;
1306 case XML_ELEMENT_CONTENT_PLUS: [s appendString:@"+"]; break;
1310 static void _elementDecl(libxmlSAXDriver *self, const xmlChar *name, int type,
1311 xmlElementContentPtr content)
1313 if (self->declHandler) {
1314 NSString *ename, *model;
1316 ename = xmlCharsToString(name);
1319 NSMutableString *emodel;
1321 emodel = [[NSMutableString alloc] init];
1322 _addElemModel(content, emodel, -1);
1323 model = [[emodel copy] autorelease];
1329 [self->declHandler elementDeclaration:ename contentModel:model];
1330 [ename release]; ename = nil;
1334 static void _attrDecl(libxmlSAXDriver *self, const xmlChar *elem,
1335 const xmlChar *name, int type, int def,
1336 const xmlChar *defaultValue, xmlEnumerationPtr tree)
1338 if (self->declHandler) {
1339 NSString *ename, *aname, *defValue, *atype, *defType;
1341 ename = xmlCharsToString(elem);
1342 aname = xmlCharsToString(name);
1343 defValue = xmlCharsToString(defaultValue);
1348 case XML_ATTRIBUTE_CDATA: atype = @"CDATA"; break;
1349 case XML_ATTRIBUTE_ID: atype = @"ID"; break;
1350 case XML_ATTRIBUTE_IDREF: atype = @"IDREF"; break;
1351 case XML_ATTRIBUTE_IDREFS: atype = @"IDREFS"; break;
1352 case XML_ATTRIBUTE_ENTITY: atype = @"ENTITY"; break;
1353 case XML_ATTRIBUTE_ENTITIES: atype = @"ENTITIES"; break;
1354 case XML_ATTRIBUTE_NMTOKEN: atype = @"NMTOKEN"; break;
1355 case XML_ATTRIBUTE_NMTOKENS: atype = @"NMTOKENS"; break;
1356 case XML_ATTRIBUTE_ENUMERATION: atype = @"ENUMERATION"; break;
1357 case XML_ATTRIBUTE_NOTATION: atype = @"NOTATION"; break;
1360 [NSException raise:@"InvalidAttributeType"
1361 format:@"don't know attr type with code %i", type];
1364 case XML_ATTRIBUTE_NONE: defType = nil; break;
1365 case XML_ATTRIBUTE_REQUIRED: defType = @"#REQUIRED"; break;
1366 case XML_ATTRIBUTE_IMPLIED: defType = @"#IMPLIED"; break;
1367 case XML_ATTRIBUTE_FIXED: defType = @"#FIXED"; break;
1370 [NSException raise:@"InvalidAttributeDefaultType"
1371 format:@"don't know attr default type with code %i", def];
1374 [self->declHandler attributeDeclaration:aname elementName:ename
1376 defaultType:defType defaultValue:defValue];
1384 static int isStandalone(libxmlSAXDriver *self) {
1386 static int hasInternalSubset(libxmlSAXDriver *self) {
1388 static int hasExternalSubset(libxmlSAXDriver *self) {
1392 static void _externalSubset(libxmlSAXDriver *ctx, const xmlChar *name,
1393 const xmlChar *ExternalID, const xmlChar *SystemID)
1396 static void _internalSubset(libxmlSAXDriver *ctx, const xmlChar *name,
1397 const xmlChar *ExternalID, const xmlChar *SystemID)
1401 static void _reference(libxmlSAXDriver *ctx, const xmlChar *name) {
1405 refName = xmlCharsToString(name);
1406 NSLog(@"reference: '%@'", refName);
1411 @end /* libxmlSAXDriver */
1413 #include "unicode.h"