mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-21 19:00:54 +00:00
Remove assertion for defined GNUSTEP_STRING_ENCODING. * GSWeb.framework/GSWDefaultAdaptorThread.m ([+sendResponse:toStream: withNamingConv:withAdditionalHeaderLines:withRemoteAddress:]): Use contentEncoding of response instead of NSISOLatin1StringEncoding. * GSWeb.framework/GSWHTMLComment.m ([-init]): Use +[GSWMessage defaultEncoding] instead of NSISOLatin1StringEncoding. * GSWeb.framework/GSWHTMLDynamicElement.m ([-addURL:forCIDKeyAssociation:CIDStoreAssociation:inContext:]): Use NSUnicodeStringEncoding instead NSISOLatin1StringEncoding for hash value. * GSWeb.framework/GSWMessage.m ([+initialize]): Set globalDefaultEncoding to NSISOLatin1StringEncoding only if WOStrictFlag default flag is set. Otherwise default to GetDefEncoding(). * GSWeb.framework/GSWRequest.m ([-_formValueEncodingFromFormData:]): Use +[GSWMessage defaultEncoding] instead of NSISOLatin1StringEncoding. ([-_formData], [-_getFormValuesFromMultipartFormDataOld]): Ditto. ([-_getFormValuesFromMultipartFormData]): Ditto. ([-_decodeMultipartBody:boundary:], -[_parseData:]): Ditto. * GSWeb.framework/GSWTemplateParserXML.m ([-templateElements]): Ditto. * GSWeb.framework/NSString+HTML.m (-[decodeURL]): Ditto. * INSTALL: Remove reference to GNUSTEP_STRING_ENCODING. * Examples/hello/HelloPage.gswc/HelloPage.gswi, * GSWExtensions.framework/French.lproj/ GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswi, GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswi * GSWExtensions.framework/ GSWCollapsibleComponentContent.gswc/GSWCollapsibleComponentContent.gswi GSWDictionaryRepetition.gswc/GSWDictionaryRepetition.gswi, GSWIFrame.gswc/GSWIFrame.gswi, GSWMetaRefresh.gswc/GSWMetaRefresh.gswi, GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.gswi, GSWRedirect.gswc/GSWRedirect.gswi, GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.gswi, GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.gswi GSWStatsPage.gswc/GSWStatsPage.gswi, GSWTable.gswc/GSWTable.gswi, GSWTableString.gswc/GSWTableString.gswi, Correct encoding declaration. * GSWExtensions.framework/ GSWKeyValueConditional.gswc/GSWKeyValueConditional.gswd, GSWKeyValueConditional.gswc/GSWKeyValueConditional.gswi, GSWKeyValueConditional.gswc/GSWKeyValueConditional.html: Correct encoding declaration and line terminators. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@20347 72102866-910b-0410-8b05-ffd578937521
1189 lines
50 KiB
Objective-C
1189 lines
50 KiB
Objective-C
/** GSWTemplateParserXML.m - <title>GSWeb: Class GSWTemplateParserXML</title>
|
|
|
|
Copyright (C) 1999-2004 Free Software Foundation, Inc.
|
|
|
|
Written by: Manuel Guesdon <mguesdon@orange-concept.com>
|
|
Date: Mar 1999
|
|
|
|
$Revision$
|
|
$Date$
|
|
$Id$
|
|
|
|
<abstract></abstract>
|
|
|
|
This file is part of the GNUstep Web Library.
|
|
|
|
<license>
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
</license>
|
|
**/
|
|
|
|
#include "config.h"
|
|
|
|
RCS_ID("$Id$")
|
|
|
|
#include "GSWeb.h"
|
|
#include "GSWTemplateParserXML.h"
|
|
#include <libxml/parser.h>
|
|
#include <libxml/parserInternals.h>
|
|
#include <libxml/SAX.h>
|
|
#include <libxml/HTMLparser.h>
|
|
|
|
extern xmlParserInputPtr xmlNewStringInputStream(xmlParserCtxtPtr ctxt,
|
|
const xmlChar *buffer);
|
|
|
|
static NSLock* GSXMLParserLock=nil;
|
|
static NSMutableDictionary* DTDCache=nil;
|
|
static NSMutableDictionary* DTDFilePathCache=nil;
|
|
|
|
@interface GSWTemplateParserSAXHandler (Private)
|
|
-(xmlParserInputPtr)resolveEntity:(NSString*)publicIdEntity
|
|
systemID:(NSString*)systemIdEntity;
|
|
@end
|
|
|
|
//====================================================================
|
|
@implementation GSWTemplateParserSAXHandler
|
|
|
|
//--------------------------------------------------------------------
|
|
+ (void) initialize
|
|
{
|
|
// Initialize DTD Cache, and Lock
|
|
if (self==[GSWTemplateParserSAXHandler class])
|
|
{
|
|
if (!DTDCache)
|
|
DTDCache=[NSMutableDictionary new];
|
|
if (!DTDFilePathCache)
|
|
DTDFilePathCache=[NSMutableDictionary new];
|
|
if (!GSXMLParserLock)
|
|
GSXMLParserLock=[NSRecursiveLock new];
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(void)dealloc
|
|
{
|
|
// Dealloc DTD Cache and Lock
|
|
if (self==[GSWTemplateParserSAXHandler class])
|
|
{
|
|
DESTROY(DTDCache);
|
|
DESTROY(DTDFilePathCache);
|
|
DESTROY(GSXMLParserLock);
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/*"Lock"*/
|
|
+(void)lock
|
|
{
|
|
NS_DURING
|
|
{
|
|
[GSXMLParserLock lock];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
NSLog(@"EXCEPTION:(GSXMLParserLock lock) %@ (%@) [%s %d]",localException,[localException reason],__FILE__,__LINE__);
|
|
[localException raise];
|
|
};
|
|
NS_ENDHANDLER;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/*"Unlock"*/
|
|
+(void)unlock
|
|
{
|
|
NS_DURING
|
|
{
|
|
[GSXMLParserLock unlock];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
NSLog(@"EXCEPTION:(GSXMLParserLock unlock) %@ (%@) [%s %d]",localException,[localException reason],__FILE__,__LINE__);
|
|
[localException raise];
|
|
};
|
|
NS_ENDHANDLER;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/** Find cached DTD Content for Key url **/
|
|
+(NSString*)cachedDTDContentForKey:(NSString*)url
|
|
{
|
|
NSString* content=nil;
|
|
[self lock];
|
|
content=[DTDCache objectForKey:url];
|
|
[self unlock];
|
|
return content;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/** Cache DTD Content externalContent for Key url **/
|
|
+(void)setCachedDTDContent:(NSString*)externalContent
|
|
forKey:(NSString*)url
|
|
{
|
|
[self lock];
|
|
[DTDCache setObject:externalContent
|
|
forKey:url];
|
|
[self unlock];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/** Find cached DTD FilePath for Key url **/
|
|
+(NSString*)cachedDTDFilePathForKey:(NSString*)url
|
|
{
|
|
NSString* filePath=nil;
|
|
[self lock];
|
|
filePath=[DTDFilePathCache objectForKey:url];
|
|
[self unlock];
|
|
return filePath;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
/** Cache DTD FilePath for Key url **/
|
|
+(void)setCachedDTDFilePath:(NSString*)filePath
|
|
forKey:(NSString*)url
|
|
{
|
|
[self lock];
|
|
[DTDFilePathCache setObject:filePath
|
|
forKey:url];
|
|
[self unlock];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(id)handlerWithTemplateParser:(GSWTemplateParser*)templateParser
|
|
{
|
|
return AUTORELEASE([[self alloc] initWithTemplateParser:templateParser]);
|
|
};
|
|
|
|
extern void externalSubset (void *ctx,
|
|
const xmlChar *name,
|
|
const xmlChar *ExternalID,
|
|
const xmlChar *SystemID);
|
|
|
|
//--------------------------------------------------------------------
|
|
-(id)initWithTemplateParser:(GSWTemplateParser*)templateParser
|
|
{
|
|
if ((self=[self init]))
|
|
{
|
|
_templateParser=templateParser;
|
|
//NSLog(@"my sax lib=%p",lib);
|
|
if (lib)
|
|
{
|
|
xmlSAXHandlerPtr def=NULL;
|
|
if ([_templateParser isKindOfClass:[GSWTemplateParserXMLHTML class]])
|
|
def=&htmlDefaultSAXHandler;
|
|
else
|
|
def=&xmlDefaultSAXHandler;
|
|
((xmlSAXHandlerPtr)lib)->internalSubset = def->internalSubset;
|
|
((xmlSAXHandlerPtr)lib)->isStandalone = def->isStandalone;
|
|
((xmlSAXHandlerPtr)lib)->hasInternalSubset = def->hasInternalSubset;
|
|
((xmlSAXHandlerPtr)lib)->hasExternalSubset = def->hasExternalSubset;
|
|
((xmlSAXHandlerPtr)lib)->resolveEntity = def->resolveEntity;
|
|
((xmlSAXHandlerPtr)lib)->getEntity = def->getEntity;
|
|
((xmlSAXHandlerPtr)lib)->entityDecl = def->entityDecl;
|
|
((xmlSAXHandlerPtr)lib)->notationDecl = def->notationDecl;
|
|
((xmlSAXHandlerPtr)lib)->attributeDecl = def->attributeDecl;
|
|
((xmlSAXHandlerPtr)lib)->elementDecl = def->elementDecl;
|
|
((xmlSAXHandlerPtr)lib)->unparsedEntityDecl = def->unparsedEntityDecl;
|
|
((xmlSAXHandlerPtr)lib)->startDocument = def->startDocument;
|
|
((xmlSAXHandlerPtr)lib)->endDocument = def->endDocument;
|
|
((xmlSAXHandlerPtr)lib)->startElement = def->startElement;
|
|
((xmlSAXHandlerPtr)lib)->endElement = def->endElement;
|
|
((xmlSAXHandlerPtr)lib)->reference = def->reference;
|
|
((xmlSAXHandlerPtr)lib)->characters = def->characters;
|
|
((xmlSAXHandlerPtr)lib)->ignorableWhitespace = def->ignorableWhitespace;
|
|
((xmlSAXHandlerPtr)lib)->processingInstruction = def->processingInstruction;
|
|
((xmlSAXHandlerPtr)lib)->comment = def->comment;
|
|
// ((xmlSAXHandlerPtr)lib)->warning = xmlParserWarning;
|
|
// ((xmlSAXHandlerPtr)lib)->error = xmlParserError;
|
|
// ((xmlSAXHandlerPtr)lib)->fatalError = xmlParserError;
|
|
((xmlSAXHandlerPtr)lib)->getParameterEntity = def->getParameterEntity;
|
|
((xmlSAXHandlerPtr)lib)->cdataBlock = def->cdataBlock;
|
|
((xmlSAXHandlerPtr)lib)->externalSubset = def->externalSubset;
|
|
};
|
|
};
|
|
return self;
|
|
};
|
|
|
|
-(id)init
|
|
{
|
|
if ((self=[super init]))
|
|
{
|
|
};
|
|
return self;
|
|
};
|
|
|
|
+ (NSString*) loadEntity: (NSString*)publicId
|
|
at: (NSString*)location
|
|
{
|
|
NSDebugMLog(@"+LOAD ENTITY pid=%@ l=%@",publicId,location);
|
|
return nil;
|
|
}
|
|
|
|
/** Should return a file path
|
|
publicId: for exemple: -//W3C//DTD XHTML 1.0 Transitional//EN
|
|
location: for exemple: xhtml1-transitional.dtd
|
|
**/
|
|
- (NSString*) loadEntity: (NSString*)publicId
|
|
at: (NSString*)location
|
|
{
|
|
NSString* filePath=nil;
|
|
LOGObjectFnStart();
|
|
NSDebugMLLog(@"GSWTemplateParser",@"loadEntity:%@ at:%@\n",
|
|
publicId,
|
|
location);
|
|
NSAssert(publicId || location,
|
|
@"resolveEntity: publicId and location are both nil");
|
|
if (location)
|
|
{
|
|
NSString* resourceName=location;
|
|
if ([[resourceName pathExtension] isEqual:@"dtd"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
filePath = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"dtd"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"location: fileName=%@ for Resource:%@",filePath,resourceName);
|
|
};
|
|
if (!filePath && publicId)
|
|
{
|
|
filePath=[[self class] cachedDTDFilePathForKey:publicId];
|
|
if (!filePath)
|
|
{
|
|
//Well Known DTDs / Entities
|
|
if ([publicId hasPrefix:@"-//"])
|
|
{
|
|
// 0: -
|
|
// 1: W3C or IETF
|
|
// 2: DTD ... or ENTITIES ...
|
|
// 3: EN or ... (language)
|
|
NSArray* parts=[publicId componentsSeparatedByString:@"//"];
|
|
if ([parts count]>=2)
|
|
{
|
|
NSString* whatPart=[parts objectAtIndex:2];
|
|
if ([whatPart hasPrefix:@"DTD"])
|
|
{
|
|
NSString* resourceName=nil;
|
|
if ([whatPart rangeOfString:@"Transitional"].length>0)
|
|
resourceName=@"xhtml1-transitional.dtd";
|
|
else if ([whatPart rangeOfString:@"Strict"].length>0)
|
|
resourceName=@"xhtml1-strict.dtd";
|
|
else if ([whatPart rangeOfString:@"Frameset"].length>0)
|
|
resourceName=@"xhtml1-frameset.dtd";
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown DTD: %@. Choose default: xhtml1-transitional.dtd",publicId);
|
|
resourceName=@"xhtml1-transitional.dtd"; // guess
|
|
};
|
|
if (resourceName)
|
|
{
|
|
if ([[resourceName pathExtension] isEqual:@"dtd"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
filePath = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"dtd"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"fileName=%@ for Resource:%@",filePath,publicId);
|
|
};
|
|
}
|
|
else if ([whatPart hasPrefix:@"ENTITIES"])
|
|
{
|
|
NSString* resourceName=nil;
|
|
if ([whatPart rangeOfString:@"Symbols"].length>0)
|
|
resourceName=@"xhtml-symbol.ent";
|
|
else if ([whatPart rangeOfString:@"Special"].length>0)
|
|
resourceName=@"xhtml-special.ent";
|
|
else if ([whatPart rangeOfString:@"Latin 1"].length>0)
|
|
resourceName=@"xhtml-lat1.ent";
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown ENTITIES: %@",publicId);
|
|
};
|
|
if (resourceName)
|
|
{
|
|
if ([[resourceName pathExtension] isEqual:@"ent"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
filePath = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"ent"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"fileName=%@ for Resource:%@",filePath,publicId);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown publicId %@",publicId);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Don't know how to parse publicId %@",publicId);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Don't know what to do with publicId %@",publicId);
|
|
};
|
|
if (filePath)
|
|
[[self class] setCachedDTDFilePath:filePath
|
|
forKey:publicId];
|
|
};
|
|
};
|
|
if (!filePath)
|
|
{
|
|
NSDebugMLog(@"Can't load external (publicId:%@ location:%@)",publicId,location);
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLLog(@"GSWTemplateParser",@"LOADED: resolveEntity:%@ location:%@ filePath:%@\n",
|
|
publicId,
|
|
location,
|
|
filePath);
|
|
};
|
|
LOGObjectFnStop();
|
|
return filePath;
|
|
|
|
}
|
|
|
|
- (void*) getEntity: (NSString*)name
|
|
{
|
|
NSDebugMLog(@"-GET ENTITY %@",name);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
xmlParserInputPtr GSWTemplateParserSAXHandler_ExternalLoader(const char *systemId,
|
|
const char *publicId,
|
|
xmlParserCtxtPtr context)
|
|
{
|
|
// NSCAssert(context,@"No Parser Context");
|
|
// NSCAssert(context->_private,@"No GSSAXHandler reference in Parser Context");
|
|
// return [(GSSAXHandler*)(context->_private)resolveEntity:[NSString stringWithCString:publicId]
|
|
// systemID:[NSString stringWithCString:systemId]];
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
//--------------------------------------------------------------------
|
|
//exemple:
|
|
// publicIdEntity
|
|
// -//IETF//DTD HTML//EN
|
|
// -//W3C//ENTITIES Special for XHTML//EN
|
|
// -//W3C//ENTITIES Symbols for XHTML//EN
|
|
// -//W3C//ENTITIES Latin 1 for XHTML//EN
|
|
// -//W3C//DTD XHTML 1.0 Transitional//EN
|
|
// -//W3C//DTD XHTML 1.0 Strict//EN
|
|
// -//W3C//DTD XHTML 1.0 Frameset//EN
|
|
// -//W3C//DTD HTML 4.01//EN
|
|
// -//W3C//DTD HTML 4.01 Transitional//EN
|
|
// -//W3C//DTD HTML 4.01 Frameset//EN
|
|
// -//IETF//DTD HTML//EN
|
|
// -//W3C//DTD HTML 3.2//EN
|
|
// systemIdEntity
|
|
// http://www.w3c.org/html.dtd
|
|
// html.dtd
|
|
|
|
-(xmlParserInputPtr)resolveEntity:(NSString*)publicIdEntity
|
|
systemID:(NSString*)systemIdEntity
|
|
{
|
|
NSString* externalContent=nil;
|
|
xmlParserInputPtr result = 0;
|
|
LOGObjectFnStart();
|
|
NSDebugMLLog(@"GSWTemplateParser",@"resolveEntity:%@ systemID:%@ inParserContext:%p\n",
|
|
publicIdEntity,
|
|
systemIdEntity,
|
|
lib);
|
|
NSAssert(publicIdEntity || systemIdEntity,
|
|
@"resolveEntity:systemIdEntity: publicIdEntity and systemIdEntity are both nil");
|
|
if (systemIdEntity)
|
|
{
|
|
externalContent=[[self class] cachedDTDContentForKey:systemIdEntity];
|
|
if (!externalContent)
|
|
{
|
|
NSString* fileName=nil;
|
|
NSString* resourceName=systemIdEntity;
|
|
if ([[resourceName pathExtension] isEqual:@"dtd"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
fileName = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"dtd"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"systemIdEntity: fileName=%@ for Resource:%@",fileName,resourceName);
|
|
if (fileName)
|
|
{
|
|
externalContent=[NSString stringWithContentsOfFile:fileName];
|
|
};
|
|
externalContent=[NSString stringWithContentsOfFile:fileName];
|
|
if (externalContent)
|
|
{
|
|
NSString* gswebTag=@"\n<!ELEMENT gsweb %Flow;>\n<!ATTLIST gsweb\n %attrs;\n >\n";
|
|
// name NMTOKEN; #IMPLIED
|
|
NSDebugMLLog(@"GSWTemplateParser",@"gswebTag=\n%@",gswebTag);
|
|
externalContent=[externalContent stringByAppendingString:gswebTag];
|
|
|
|
[[self class] setCachedDTDContent:externalContent
|
|
forKey:systemIdEntity];
|
|
};
|
|
};
|
|
};
|
|
if (!externalContent && publicIdEntity)
|
|
{
|
|
externalContent=[[self class] cachedDTDContentForKey:publicIdEntity];
|
|
if (!externalContent)
|
|
{
|
|
//Well Known DTDs / Entities
|
|
if ([publicIdEntity hasPrefix:@"-//"])
|
|
{
|
|
// 0: -
|
|
// 1: W3C or IETF
|
|
// 2: DTD ... or ENTITIES ...
|
|
// 3: EN or ... (language)
|
|
NSArray* parts=[publicIdEntity componentsSeparatedByString:@"//"];
|
|
if ([parts count]>=2)
|
|
{
|
|
NSString* whatPart=[parts objectAtIndex:2];
|
|
if ([whatPart hasPrefix:@"DTD"])
|
|
{
|
|
NSString* resourceName=nil;
|
|
NSString* fileName=nil;
|
|
if ([whatPart rangeOfString:@"Transitional"].length>0)
|
|
resourceName=@"xhtml1-transitional.dtd";
|
|
else if ([whatPart rangeOfString:@"Strict"].length>0)
|
|
resourceName=@"xhtml1-strict.dtd";
|
|
else if ([whatPart rangeOfString:@"Frameset"].length>0)
|
|
resourceName=@"xhtml1-frameset.dtd";
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown DTD: %@. Choose default: xhtml1-transitional.dtd",publicIdEntity);
|
|
resourceName=@"xhtml1-transitional.dtd"; // guess
|
|
};
|
|
if (resourceName)
|
|
{
|
|
if ([[resourceName pathExtension] isEqual:@"dtd"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
fileName = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"dtd"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"systemIdEntity: fileName=%@ for Resource:%@",fileName,publicIdEntity);
|
|
if (fileName)
|
|
{
|
|
externalContent=[NSString stringWithContentsOfFile:fileName];
|
|
};
|
|
};
|
|
}
|
|
else if ([whatPart hasPrefix:@"ENTITIES"])
|
|
{
|
|
NSString* resourceName=nil;
|
|
NSString* fileName=nil;
|
|
if ([whatPart rangeOfString:@"Symbols"].length>0)
|
|
resourceName=@"xhtml-symbol.ent";
|
|
else if ([whatPart rangeOfString:@"Special"].length>0)
|
|
resourceName=@"xhtml-special.ent";
|
|
else if ([whatPart rangeOfString:@"Latin 1"].length>0)
|
|
resourceName=@"xhtml-lat1.ent";
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown ENTITIES: %@",publicIdEntity);
|
|
};
|
|
if (resourceName)
|
|
{
|
|
if ([[resourceName pathExtension] isEqual:@"ent"])
|
|
resourceName=[resourceName stringByDeletingPathExtension];
|
|
fileName = [[NSBundle bundleForClass: [self class]]
|
|
pathForResource:resourceName
|
|
ofType:@"ent"
|
|
inDirectory:@"DTDs"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"systemIdEntity: fileName=%@ for Resource:%@",fileName,publicIdEntity);
|
|
if (fileName)
|
|
{
|
|
externalContent=[NSString stringWithContentsOfFile:fileName];
|
|
};
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Unknown publicIdEntity %@",publicIdEntity);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Don't know how to parse publicIdEntity %@",publicIdEntity);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
NSDebugMLog(@"Don't know what to do with publicIdEntity %@",publicIdEntity);
|
|
};
|
|
if (externalContent)
|
|
[[self class] setCachedDTDContent:externalContent
|
|
forKey:publicIdEntity];
|
|
};
|
|
};
|
|
if (externalContent)
|
|
{
|
|
result=xmlNewStringInputStream(lib,[externalContent cString]);
|
|
};
|
|
NSAssert2(result,@"Can't load external (publicIdEntity:%@ systemIdEntity:%@)",publicIdEntity,systemIdEntity);
|
|
NSDebugMLLog(@"GSWTemplateParser",@"LOADED: resolveEntity:%@ systemID:%@ inParserContext:%p\n",
|
|
publicIdEntity,
|
|
systemIdEntity,
|
|
lib);
|
|
LOGObjectFnStop();
|
|
return result;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)warning:(NSString*)message
|
|
colNumber:(int)colNumber
|
|
lineNumber:(int)lineNumber
|
|
{
|
|
[[GSWApplication application] logWithFormat:@"%@ Warning (col %d,line %d): %@",
|
|
[_templateParser logPrefix],
|
|
colNumber,
|
|
lineNumber,
|
|
message];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)error: (NSString*)message
|
|
colNumber:(int)colNumber
|
|
lineNumber:(int)lineNumber
|
|
{
|
|
NSString* testMessage=[[message lowercaseString] stringByTrimmingSpaces];
|
|
if (![testMessage isEqualToString:@"tag webobject invalid"]
|
|
&& ![testMessage isEqualToString:@"tag gsweb invalid"]
|
|
&& ![testMessage isEqualToString:@"htmlparsestarttag: misplaced <html> tag"]
|
|
&& ![testMessage isEqualToString:@"htmlparsestarttag: misplaced <head> tag"]
|
|
&& ![testMessage isEqualToString:@"unexpected end tag : head"])
|
|
{
|
|
[[GSWApplication application] logErrorWithFormat:@"%@ Error (line %d,col %d): %@",
|
|
[_templateParser logPrefix],
|
|
lineNumber,
|
|
colNumber,
|
|
message];
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)fatalError: (NSString*)message
|
|
colNumber:(int)colNumber
|
|
lineNumber:(int)lineNumber
|
|
{
|
|
[[GSWApplication application] logErrorWithFormat:@"%@ Fatal Error (line %d,col %d): %@",
|
|
[_templateParser logPrefix],
|
|
lineNumber,
|
|
colNumber,
|
|
message];
|
|
};
|
|
|
|
@end
|
|
|
|
//====================================================================
|
|
@implementation GSWTemplateParserXML
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)dealloc
|
|
{
|
|
DESTROY(_xmlDocument);
|
|
[super dealloc];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
static NSString* TabsForLevel(int level)
|
|
{
|
|
int i=0;
|
|
NSMutableString* tabs=[NSMutableString string];
|
|
for (i=0;i<level;i++)
|
|
{
|
|
[tabs appendString:@"\t"];
|
|
};
|
|
return tabs;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)dumpNode:(GSXMLNode*)node
|
|
atLevel:(int)level
|
|
{
|
|
NSString* dumpString=[NSString string];
|
|
LOGObjectFnStart();
|
|
while (node)
|
|
{
|
|
const char* content=[[node content] lossyCString];
|
|
dumpString=[dumpString stringByAppendingFormat:@"%@%@ [Type:%@] [%@]%s%s\n",
|
|
TabsForLevel(level),
|
|
[node name],
|
|
[node typeDescription],
|
|
[node propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
(content ? ":\n" : ""),
|
|
(content ? content : "")];
|
|
if ([node firstChild])
|
|
dumpString=[dumpString stringByAppendingString:[self dumpNode:[node firstChild]
|
|
atLevel:level+1]];
|
|
node=[node next];
|
|
};
|
|
LOGObjectFnStop();
|
|
return dumpString;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSArray*)templateElements
|
|
{
|
|
NSArray* elements=nil;
|
|
LOGObjectFnStart();
|
|
if (!_xmlDocument)
|
|
{
|
|
BOOL parseOk=NO;
|
|
GSXMLParser* parser=nil;
|
|
GSWTemplateParserSAXHandler* sax=nil;
|
|
NSStringEncoding stringEncoding=_stringEncoding;
|
|
|
|
if (stringEncoding==GSUndefinedEncoding)
|
|
stringEncoding=[GSWMessage defaultEncoding];
|
|
|
|
sax=[GSWTemplateParserSAXHandler handlerWithTemplateParser:self];
|
|
if ([self isKindOfClass:[GSWTemplateParserXMLHTML class]])
|
|
{
|
|
NSRange tagRange=NSMakeRange(NSNotFound,0);
|
|
tagRange=[_string rangeOfString:@"<HTML"
|
|
options:NSCaseInsensitiveSearch];
|
|
//NSDebugMLLog(@"GSWTemplateParser",@"HTML Tag Range length=%d",tagRange.length);
|
|
if (tagRange.length>0)
|
|
_isHTMLTag=YES;
|
|
tagRange=[_string rangeOfString:@"<BODY"
|
|
options:NSCaseInsensitiveSearch];
|
|
//NSDebugMLLog(@"GSWTemplateParser",@"BODY Tag Range length=%d",tagRange.length);
|
|
if (tagRange.length>0)
|
|
_isBodyTag=YES;
|
|
parser=[GSHTMLParser parserWithSAXHandler:sax
|
|
withData:[_string dataUsingEncoding:stringEncoding]];
|
|
NSDebugMLog(@"_string (%d)=%@",[_string length],_string);
|
|
}
|
|
else
|
|
{
|
|
NSData* dataToParse=nil;
|
|
NSString* xmlHeader=nil;
|
|
//NSRange docTypeRange=NSMakeRange(NSNotFound,0);
|
|
NSString* stringToParse=nil;
|
|
NSString* encodingString=nil;
|
|
encodingString=[GSXMLParser xmlEncodingStringForStringEncoding:stringEncoding];
|
|
if (encodingString)
|
|
encodingString=[NSString stringWithFormat:@" encoding=\"%@\"",encodingString];
|
|
else
|
|
encodingString=@"";
|
|
|
|
stringToParse=_string;
|
|
|
|
// Add a <gsweb> null tag around the code because libxml parser doesn't support <tag>..</tag><tag>..</tag>...
|
|
stringToParse=[NSString stringWithFormat:@"<gsweb>\n%@\n</gsweb>\n",stringToParse];
|
|
|
|
// Build the header
|
|
xmlHeader=[NSString stringWithFormat:@"<?xml version=\"%@\"%@?>\n",
|
|
@"1.0",
|
|
encodingString];
|
|
|
|
/* Don't care about DOCTYPE !
|
|
docTypeRange=[stringToParse rangeOfString:@"<!DOCTYPE"];
|
|
if (docTypeRange.length==0)
|
|
stringToParse=[@"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"xhtml1-transitional.dtd\">\n"
|
|
stringByAppendingString:stringToParse];
|
|
*/
|
|
stringToParse=[xmlHeader stringByAppendingString:stringToParse];
|
|
NSDebugMLog(@"stringToParse (%d)=%@",[stringToParse length],stringToParse);
|
|
dataToParse=[stringToParse dataUsingEncoding:stringEncoding];
|
|
_isHTMLTag=YES; // Don't remove HTML tags in parsed tree
|
|
_isBodyTag=YES; // Don't remove BODY tags in parsed tree
|
|
parser=[GSXMLParser parserWithSAXHandler:sax
|
|
withData:dataToParse];
|
|
[parser keepBlanks:YES];
|
|
};
|
|
[parser doValidityChecking:YES];
|
|
[parser getWarnings:YES];
|
|
//[parser setExternalEntityLoader:GSWTemplateParserSAXHandler_ExternalLoader];
|
|
NS_DURING
|
|
{
|
|
parseOk=[parser parse];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGError(@"%@ Exception in parse! Exception: %@",
|
|
[self logPrefix],
|
|
localException);
|
|
localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
|
|
@"%@ - In [parser parse] Exception!",
|
|
[self logPrefix]);
|
|
[localException retain];
|
|
[localException autorelease];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
if (!parseOk)
|
|
{
|
|
int errNo=[parser errNo];
|
|
// We point out only deep error
|
|
switch(errNo)
|
|
{
|
|
case XML_ERR_NO_DTD:
|
|
NSDebugMLLog(@"GSWTemplateParser",@"%@ - Warning: No DTD",
|
|
[self logPrefix]);
|
|
break;
|
|
default:
|
|
NSDebugMLLog(@"GSWTemplateParser",@"######Parse FAILED errNo=%d [parser document]=%p",
|
|
[parser errNo],
|
|
[parser document]);
|
|
break;
|
|
};
|
|
// May be validity errors only (like no HTML root)
|
|
if ([parser document])
|
|
parseOk=YES;
|
|
};
|
|
if (parseOk)
|
|
{
|
|
GSXMLNode* node=nil;
|
|
NSDebugMLLog(@"GSWTemplateParser",@"Root");
|
|
ASSIGN(_xmlDocument,[parser document]);
|
|
node=[_xmlDocument root];
|
|
NSAssert1(node,@"%@ Empty Document (root)",
|
|
[self logPrefix]);
|
|
#ifndef NDEBUG
|
|
{
|
|
NSString* dumpString=[self dumpNode:node
|
|
atLevel:0];
|
|
NSDebugMLLog0(@"low",@"Will dump _xmlDocument");
|
|
NSDebugMLLog(@"GSWTemplateParser",@"%@ _xmlDocument=\n%@",
|
|
[self logPrefix],
|
|
dumpString);
|
|
NSDebugMLLog0(@"low",@"_xmlDocument dumped");
|
|
};
|
|
#endif
|
|
/*
|
|
if ([node type]==XML_DTD_NODE) {
|
|
NSLog(@"GSWTemplateParserXML: XML_DTD_NODE is found");
|
|
}
|
|
|
|
NSLog(@"ROOT node=%p %@ [Type:%@] [%@] ##%s##\n",
|
|
node,
|
|
[node name],
|
|
[node typeDescription],
|
|
[node propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
[[node content] lossyCString]);
|
|
*/
|
|
|
|
/* if (node->type!=XML_DTD_NODE)
|
|
{
|
|
NSLog(@"Bad first node type: %@ instead of %@",
|
|
[nodeTypes objectForKey:[NSString stringWithFormat:@"%d",(int)node->type]],
|
|
[nodeTypes objectForKey:[NSString stringWithFormat:@"%d",(int)XML_DTD_NODE]]);
|
|
};
|
|
*/
|
|
// NSDebugMLLog(@"GSWTemplateParser",@"Test Root");
|
|
if ([node type]!=XML_ELEMENT_NODE)
|
|
node=[node firstChild];
|
|
// NSDebugMLLog(@"GSWTemplateParser",@"Test Root children");
|
|
NSAssert1(node,@"%@ Empty Document ([root firstChild])",
|
|
[self logPrefix]);
|
|
if ([node type]!=XML_ELEMENT_NODE)
|
|
node=[node next];
|
|
// NSDebugMLLog(@"GSWTemplateParser",@"Test Root children Next");
|
|
NSAssert1(node,@"%@ Empty Document ([[root firstChild] next])",
|
|
[self logPrefix]);
|
|
//Remove html and body node when they have been added by html parser
|
|
if (!_isHTMLTag || !_isBodyTag)
|
|
{
|
|
BOOL cont=YES;
|
|
while (node && cont)
|
|
{
|
|
cont=NO;
|
|
if ([node type]==XML_ELEMENT_NODE)
|
|
{
|
|
NSString* nodeName=[node name];
|
|
/* NSDebugMLLog(@"GSWTemplateParser",@"node name=%@",nodeName);
|
|
NSDebugMLLog(@"GSWTemplateParser",@"_isHTMLTag=%s _isBodyTag=%s",
|
|
(_isHTMLTag ? "YES" : "NO"),
|
|
(_isBodyTag ? "YES" : "NO"));
|
|
*/
|
|
/*
|
|
NSLog(@"while1 node=%p %@ [Type:%@] [%@] ##%s##\n",
|
|
node,
|
|
[node name],
|
|
[node typeDescription],
|
|
[node propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
[[node content] lossyCString]);
|
|
*/
|
|
if ((!_isHTMLTag && [nodeName caseInsensitiveCompare:@"html"]==NSOrderedSame)
|
|
|| (!_isBodyTag && [nodeName caseInsensitiveCompare:@"body"]==NSOrderedSame))
|
|
{
|
|
// NSDebugMLLog(@"GSWTemplateParser",@"==> Children");
|
|
node=[node firstChild];
|
|
cont=YES;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
if (node)
|
|
{
|
|
//NSDebugMLLog(@"GSWTemplateParser",@"Call createElementsFromNode:");
|
|
NS_DURING
|
|
{
|
|
gswebTagN=0;
|
|
tagN=0;
|
|
elements=[self createElementsFromNode:node];
|
|
// If we've found error raise exception
|
|
NSDebugMLog(@"_errorMessages=%@",_errorMessages);
|
|
if ([[self errorMessages]count]>0)
|
|
{
|
|
NSDebugMLog(@"declarationsFilePath=%@",_declarationsFilePath);
|
|
ExceptionRaise(@"GSWTemplateParser",@"%@\nDefinitionFiles: %@",
|
|
[self errorMessagesAsText],
|
|
_processedDeclarationsFilePaths);
|
|
};
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGError(@"%@ Exception in elements creation!",
|
|
[self logPrefix]);
|
|
localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
|
|
@"%@ - Exception in elements creation",
|
|
[self logPrefix]);
|
|
[localException retain];
|
|
[localException autorelease];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
};
|
|
};
|
|
};
|
|
LOGObjectFnStop();
|
|
return elements;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
/*
|
|
text [Type:XML_TEXT_NODE] [{}] ####
|
|
head [Type:XML_ELEMENT_NODE] [{}] ##(null)##
|
|
title [Type:XML_ELEMENT_NODE] [{}] ##(null)##
|
|
text [Type:XML_TEXT_NODE] [{}] ##MyTitle##
|
|
text [Type:XML_TEXT_NODE] [{}] ####
|
|
body [Type:XML_ELEMENT_NODE] [{bgcolor = white; }] ##(null)##
|
|
text [Type:XML_TEXT_NODE] [{}] ####
|
|
gsweb [Type:XML_ELEMENT_NODE] [{name = MyObject; }] ##(null)##
|
|
text [Type:XML_TEXT_NODE] [{}] ##AText##
|
|
p [Type:XML_ELEMENT_NODE] [{align = center; }] ##(null)##
|
|
text [Type:XML_TEXT_NODE] [{}] ##Text2##
|
|
b [Type:XML_ELEMENT_NODE] [{}] ##(null)##
|
|
text [Type:XML_TEXT_NODE] [{}] ##Text3##
|
|
text [Type:XML_TEXT_NODE] [{}] ####
|
|
text [Type:XML_TEXT_NODE] [{}] ##TEXTB##
|
|
comment [Type:XML_COMMENT_NODE] [{}] ##MyComment##
|
|
text [Type:XML_TEXT_NODE] [{}] ##TEXTC##
|
|
text [Type:XML_TEXT_NODE] [{}] ####
|
|
*/
|
|
-(NSArray*)createElementsFromNode:(GSXMLNode*)node
|
|
{
|
|
GSXMLNode* currentNode=node;
|
|
NSMutableArray* _elements=nil;
|
|
NSAutoreleasePool* arp = nil;
|
|
BOOL includesComment = NO;
|
|
LOGObjectFnStart();
|
|
includesComment=[GSWApplication includeCommentsInResponses];
|
|
_elements=[NSMutableArray array];
|
|
arp=[NSAutoreleasePool new];
|
|
GSWLogMemCF("New NSAutoreleasePool: %p",arp);
|
|
NS_DURING
|
|
{
|
|
while(currentNode)
|
|
{
|
|
GSWElement* elem=nil;
|
|
NSDebugMLLog(@"GSWTemplateParser",@"BEGIN node=%p %@ [Type:%@] [%@] ##%s##\n",
|
|
currentNode,
|
|
[currentNode name],
|
|
[currentNode typeDescription],
|
|
[currentNode propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
/* ((xmlNodePtr)[currentNode lib])->content,
|
|
[currentNode content],*/
|
|
[[currentNode content] lossyCString]);
|
|
|
|
switch([currentNode type])
|
|
{
|
|
case XML_TEXT_NODE:
|
|
{
|
|
NSDebugMLog0(@"TEXT");
|
|
|
|
if ([currentNode content] && ([[currentNode content] length] > 0) ) {
|
|
|
|
elem=[GSWHTMLBareString elementWithString:
|
|
[NSString stringWithCString:
|
|
[[[currentNode content]
|
|
stringByConvertingToHTMLEntities]
|
|
lossyCString]]];//Because XML Parser decode characters
|
|
} else {
|
|
elem = nil;
|
|
}
|
|
|
|
NSDebugMLLog(@"GSWTemplateParser",@"TEXT element=%@",elem);
|
|
};
|
|
break;
|
|
case XML_CDATA_SECTION_NODE:
|
|
{
|
|
NSDebugMLog0(@"CDATA_SECTION");
|
|
NSDebugMLLog(@"GSWTemplateParser",@"CDATA_SECTION content=%s",[[currentNode content] lossyCString]);
|
|
elem=[GSWHTMLBareString elementWithString:[currentNode content]];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"CDATA_SECTION element=%@",elem);
|
|
};
|
|
break;
|
|
case XML_COMMENT_NODE:
|
|
{
|
|
NSDebugMLog0(@"COMMENT");
|
|
if (includesComment)
|
|
{
|
|
elem=[GSWHTMLBareString elementWithString:[NSString stringWithFormat:@"<!-- %s -->",[[currentNode content] lossyCString]]];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"COMMENT element=%@",elem);
|
|
};
|
|
};
|
|
break;
|
|
default:
|
|
{
|
|
int currentGSWebTagN=0;
|
|
int currentTagN=0;
|
|
NSArray* children=nil;
|
|
NSDictionary* nodeAttributes=nil;
|
|
NSString* nodeName=nil;
|
|
NSString* nodeNameAttribute=nil;
|
|
nodeName=[currentNode name];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"DEFAULT (name=%@ type=%@)",nodeName,[currentNode typeDescription]);
|
|
//if (currentNode->type==XML_ELEMENT_NODE)
|
|
{
|
|
nodeAttributes=[currentNode propertiesAsDictionaryWithKeyTransformationSel:@selector(lowercaseString)];
|
|
nodeNameAttribute=[nodeAttributes objectForKey:@"name"];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p nodeAttributes=%@",currentNode,nodeAttributes);
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p nodeNameAttribute=%@",currentNode,nodeNameAttribute);
|
|
tagN++;
|
|
if ([nodeName caseInsensitiveCompare:GSWTag_Name[GSWNAMES_INDEX]]==NSOrderedSame
|
|
||[nodeName caseInsensitiveCompare:GSWTag_Name[WONAMES_INDEX]]==NSOrderedSame)
|
|
gswebTagN++;
|
|
currentGSWebTagN=gswebTagN;
|
|
currentTagN=tagN;
|
|
if ([currentNode firstChild])
|
|
{
|
|
children=[self createElementsFromNode:[currentNode firstChild]];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p children=%@",currentNode,children);
|
|
};
|
|
if ([nodeName caseInsensitiveCompare:GSWTag_Name[GSWNAMES_INDEX]]==NSOrderedSame
|
|
||[nodeName caseInsensitiveCompare:GSWTag_Name[WONAMES_INDEX]]==NSOrderedSame)
|
|
{
|
|
GSWDeclaration* declaration=nil;
|
|
if (!nodeNameAttribute)
|
|
{
|
|
// allow null name tags
|
|
elem=[GSWHTMLStaticGroup elementWithContentElements:children];
|
|
}
|
|
else
|
|
{
|
|
NSDictionary* _associations=nil;
|
|
NSString* className=nil;
|
|
GSWHTMLStaticGroup* aStaticGroup=nil;
|
|
declaration=[_declarations objectForKey:nodeNameAttribute];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"declaration:[%@]",
|
|
declaration);
|
|
NSDebugMLLog(@"GSWTemplateParser",@"GSWeb Tag declaration:[%@]",
|
|
declaration);
|
|
if (!declaration)
|
|
{
|
|
// We don't raise exception know because it's better for developper to collect and report all errors before :-)
|
|
[self addErrorMessageFormat:@"No element definition for tag named:%@ [#%d,#%d]",
|
|
nodeNameAttribute,
|
|
currentGSWebTagN,
|
|
currentTagN];
|
|
}
|
|
else
|
|
{
|
|
_associations=[declaration associations];
|
|
className=[declaration type];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p GSWeb Tag className:[%@]",currentNode,className);
|
|
if (!className)
|
|
{
|
|
// We don't raise exception know because it's better for developper to collect and report all errors before :-)
|
|
[self addErrorMessageFormat:@"No class name in page definition for tag named:%@ declaration=%@ [#%d,#%d]",
|
|
nodeNameAttribute,
|
|
declaration,
|
|
currentGSWebTagN,
|
|
currentTagN];
|
|
};
|
|
};
|
|
// No class name mean we'll raise an exception after so don't care about this part...
|
|
if (className) //
|
|
{
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p associations:%@",currentNode,_associations);
|
|
{
|
|
NSEnumerator* _nodeAttributesEnum = [nodeAttributes keyEnumerator];
|
|
id _tagAttrKey=nil;
|
|
id _tagAttrValue=nil;
|
|
NSMutableDictionary* _addedAssoc=nil;
|
|
while ((_tagAttrKey = [_nodeAttributesEnum nextObject]))
|
|
{
|
|
if (![_tagAttrKey isEqualToString:@"name"] && ![_associations objectForKey:_tagAttrKey])
|
|
{
|
|
if (!_addedAssoc)
|
|
_addedAssoc=(NSMutableDictionary*)[NSMutableDictionary dictionary];
|
|
_tagAttrValue=[nodeAttributes objectForKey:_tagAttrKey];
|
|
[_addedAssoc setObject:[GSWAssociation associationWithValue:_tagAttrValue]
|
|
forKey:_tagAttrKey];
|
|
};
|
|
};
|
|
if (_addedAssoc)
|
|
{
|
|
_associations=[_associations dictionaryByAddingEntriesFromDictionary:_addedAssoc];
|
|
};
|
|
};
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p gsweb name=%@ dynamicElementWithName: children=%@",
|
|
currentNode,
|
|
nodeNameAttribute,
|
|
children);
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p %@ [Type:%@] [%@] ##%s##\n",
|
|
currentNode,
|
|
[currentNode name],
|
|
[currentNode typeDescription],
|
|
[currentNode propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
[[currentNode content] lossyCString]);
|
|
aStaticGroup=[[[GSWHTMLStaticGroup alloc]initWithContentElements:children]autorelease];
|
|
elem=[GSWApp dynamicElementWithName:className
|
|
associations:_associations
|
|
template:aStaticGroup
|
|
languages:_languages];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p element=%@ StaticGroup %p=%@",currentNode,elem,aStaticGroup,aStaticGroup);
|
|
if (elem)
|
|
[elem setDeclarationName:[declaration name]];
|
|
else
|
|
{
|
|
// We don't raise exception know because it's better for developper to collect and report all errors before :-)
|
|
[self addErrorMessageFormat:@"Creation failed for element named:%@ className:%@",
|
|
[declaration name],
|
|
className];
|
|
};
|
|
};
|
|
};
|
|
}
|
|
else
|
|
{
|
|
//It's a hack to remove html & body elements where there's not in the template (HTML parser add them when there are missing)
|
|
if ((!_isHTMLTag
|
|
&& [nodeName caseInsensitiveCompare:@"html"]==NSOrderedSame
|
|
&& [nodeAttributes count]==0)
|
|
|| (!_isBodyTag
|
|
&& [nodeName caseInsensitiveCompare:@"body"]==NSOrderedSame
|
|
&& [nodeAttributes count]==0))
|
|
{
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p StaticElement: children=%@",currentNode,children);
|
|
elem=[[[GSWHTMLStaticElement alloc]initWithName:nil
|
|
attributeDictionary:nil
|
|
contentElements:children]autorelease];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p element=%@",currentNode,elem);
|
|
}
|
|
else
|
|
{
|
|
NSDictionary* _associations=nil;
|
|
NSEnumerator* _nodeAttributesEnum = [nodeAttributes keyEnumerator];
|
|
id _tagAttrKey=nil;
|
|
id _tagAttrValue=nil;
|
|
NSMutableDictionary* _addedAssoc=nil;
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p Create nodeName=%@ nodeAttributes=%@",
|
|
currentNode,nodeName,nodeAttributes);
|
|
while ((_tagAttrKey = [_nodeAttributesEnum nextObject]))
|
|
{
|
|
//Don't remove name for not gsweb tag
|
|
//if (![_tagAttrKey isEqualToString:@"name"] && ![_associations objectForKey:_tagAttrKey])
|
|
if (![_associations objectForKey:_tagAttrKey])
|
|
{
|
|
if (!_addedAssoc)
|
|
_addedAssoc=(NSMutableDictionary*)[NSMutableDictionary dictionary];
|
|
_tagAttrValue=[nodeAttributes objectForKey:_tagAttrKey];
|
|
[_addedAssoc setObject:[GSWAssociation associationWithValue:_tagAttrValue]
|
|
forKey:_tagAttrKey];
|
|
};
|
|
};
|
|
if (_addedAssoc)
|
|
{
|
|
_associations=[NSDictionary dictionaryWithDictionary:_addedAssoc];
|
|
};
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p Create nodeName=%@ nodeAttributes=%@ _associations=%@",
|
|
currentNode,nodeName,nodeAttributes,_associations);
|
|
//To know if it's an autoclose tag
|
|
if (!children && [self isKindOfClass:[GSWTemplateParserXMLHTML class]])
|
|
{
|
|
const htmlElemDesc* elemDscr=htmlTagLookup([nodeName lossyCString]);
|
|
if (elemDscr
|
|
&& elemDscr->endTag!=2 //Forbidden End Tag
|
|
&& elemDscr->endTag!=1) //End can be omitted
|
|
{
|
|
children=[NSArray array];
|
|
};
|
|
};
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p StaticElement: children=%@",currentNode,children);
|
|
elem=[[[GSWHTMLStaticElement alloc]initWithName:nodeName
|
|
attributeDictionary:_associations
|
|
contentElements:children]autorelease];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"node=%p element=%@",currentNode,elem);
|
|
};
|
|
};
|
|
};
|
|
};
|
|
break;
|
|
};
|
|
if (elem)
|
|
[_elements addObject:elem];
|
|
NSDebugMLLog(@"GSWTemplateParser",@"END node=%p %@ [Type:%@] [%@] ##%s##\n",
|
|
currentNode,
|
|
[currentNode name],
|
|
[currentNode typeDescription],
|
|
[currentNode propertiesAsDictionaryWithKeyTransformationSel:NULL],
|
|
[[currentNode content] lossyCString]);
|
|
currentNode=[currentNode next];
|
|
};
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGError(@"%@ createElementsFromNode: Exception",
|
|
[self logPrefix]);
|
|
localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
|
|
@"%@ In [GSWTemplateParserXML createElementsFromNode:]...",
|
|
[self logPrefix]);
|
|
[localException retain];
|
|
GSWLogMemCF("Destroy NSAutoreleasePool: %p",arp);
|
|
DESTROY(arp);
|
|
[localException autorelease];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
GSWLogMemCF("Destroy NSAutoreleasePool: %p",arp);
|
|
DESTROY(arp);
|
|
LOGObjectFnStop();
|
|
NSDebugMLLog(@"GSWTemplateParser",@"_elements=%@",_elements);
|
|
return _elements;
|
|
};
|
|
|
|
@end
|
|
|
|
|
|
//====================================================================
|
|
// used only for XML/XMLHTML differences
|
|
@implementation GSWTemplateParserXMLHTML
|
|
|
|
/** call htmlHandleOmittedElem(0) if YES, htmlHandleOmittedElem(1) if NO; **/
|
|
-(void)setNoOmittedTags:(BOOL)yn
|
|
{
|
|
htmlHandleOmittedElem(yn ? 0 : 1);
|
|
};
|
|
|
|
@end
|
|
|