diff --git a/ChangeLog b/ChangeLog index bf9def572..57f7ca271 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-05-12 Richard Frith-Macdonald + + * Source/Additions/GSXML.m: New -escapedContent method to provide + text with the five entities libxml automatically substitutes even + when told not to. + * Tools/AGSHtml.m: Use -escapedContent to get text suitable for + output in html documents. + 2003-05-11 Richard Frith-Macdonald * Tools/gdomap.8.gz: Added man page adapted from internal docs by diff --git a/Headers/gnustep/base/GSXML.h b/Headers/gnustep/base/GSXML.h index df7f2c83c..74455ad13 100644 --- a/Headers/gnustep/base/GSXML.h +++ b/Headers/gnustep/base/GSXML.h @@ -114,6 +114,7 @@ - (NSDictionary*) attributes; - (NSString*) content; - (GSXMLDocument*) document; +- (NSString*) escapedContent; - (GSXMLAttribute*) firstAttribute; - (GSXMLNode*) firstChild; - (GSXMLNode*) firstChildElement; diff --git a/Source/Additions/GSXML.m b/Source/Additions/GSXML.m index d9d2c4ce0..7c61edd04 100644 --- a/Source/Additions/GSXML.m +++ b/Source/Additions/GSXML.m @@ -820,7 +820,13 @@ static NSMapTable *nodeNames = 0; * entity reference nodes, in this case you should not use this * method to get the content of the element, but should examine * the child nodes of the element individually and perform any - * entity reference you need to do explicitly. + * entity reference you need to do explicitly.
+ * NB. There are five standard entities which are automatically + * substituted into the content text rather than appearing as + * entity nodes in their own right. These are '<', '>', ''', + * '"' and '&'. If you with to receive content in which these + * characters are represented by the original entity escapes, you need + * to use the -escapedContent method. */ - (NSString*) content { @@ -893,6 +899,112 @@ static NSMapTable *nodeNames = 0; } } +/** + * This performs the same function as the -content method, but retains + * the standard five entities (&lt;, &gt;, &apos;, &quot;, + * and &amp;) which are normally replaced with their standard equivalents + * (<, >, ', ", and &).
+ */ +- (NSString*) escapedContent +{ + NSString *str = [self content]; + + if (str != nil) + { + static NSCharacterSet *set = nil; + + if (set == nil) + { + set = [NSCharacterSet characterSetWithCharactersInString: @"<>'\"&"]; + RETAIN(set); + } + if ([str rangeOfCharacterFromSet: set].length > 0) + { + unichar *base; + unichar *map; + unichar c; + unsigned len; + unsigned rpos; + unsigned wpos; + unsigned end = [str length]; + + base = NSZoneMalloc(NSDefaultMallocZone(), end * sizeof(unichar)); + [str getCharacters: base]; + for (len = rpos = 0; rpos < end; rpos++) + { + c = base[rpos]; + switch (c) + { + case '&': + len += 5; + break; + case '<': + case '>': + len += 4; + break; + case '\'': + case '"': + len += 6; + break; + default: + len++; + break; + } + } + map = NSZoneMalloc(NSDefaultMallocZone(), len * sizeof(unichar)); + for (wpos = rpos = 0; rpos < end; rpos++) + { + c = base[rpos]; + switch (c) + { + case '&': + map[wpos++] = '&'; + map[wpos++] = 'a'; + map[wpos++] = 'm'; + map[wpos++] = 'p'; + map[wpos++] = ';'; + break; + case '<': + map[wpos++] = '&'; + map[wpos++] = 'l'; + map[wpos++] = 't'; + map[wpos++] = ';'; + break; + case '>': + map[wpos++] = '&'; + map[wpos++] = 'g'; + map[wpos++] = 't'; + map[wpos++] = ';'; + break; + case '\'': + map[wpos++] = '&'; + map[wpos++] = 'a'; + map[wpos++] = 'p'; + map[wpos++] = 'o'; + map[wpos++] = 's'; + map[wpos++] = ';'; + break; + case '"': + map[wpos++] = '&'; + map[wpos++] = 'q'; + map[wpos++] = 'u'; + map[wpos++] = 'o'; + map[wpos++] = 't'; + map[wpos++] = ';'; + break; + default: + map[wpos++] = c; + break; + } + } + NSZoneFree(NSDefaultMallocZone(), base); + str = [[NSString alloc] initWithCharacters: map length: len]; + AUTORELEASE(str); + } + } + return str; +} + /** * Return the first attribute in this node. */ diff --git a/Source/GSFormat.m b/Source/GSFormat.m index 85bcf44d9..932829670 100644 --- a/Source/GSFormat.m +++ b/Source/GSFormat.m @@ -922,7 +922,7 @@ NSDictionary *locale) if (grouping == (const char *) -1) { thousands_sep = [locale objectForKey: NSThousandsSeparator]; - if (!thousands_sep) thousands_sep = @","; + if (thousands_sep == nil) thousands_sep = @","; grouping = ""; // FIXME: grouping info missing in locale? if (*grouping == '\0' || *grouping == CHAR_MAX) @@ -1405,6 +1405,7 @@ NSDictionary *locale) NSString *decimal_sep; decimal_sep = [locale objectForKey: NSDecimalSeparator]; + if (decimal_sep == nil) decimal_sep = @"."; bp = buf1; @@ -1525,6 +1526,7 @@ NSDictionary *locale) NSString *decimal_sep; decimal_sep = [locale objectForKey: NSDecimalSeparator]; + if (decimal_sep == nil) decimal_sep = @"."; bp = buf1; diff --git a/Tools/AGSHtml.m b/Tools/AGSHtml.m index c5758f281..58486912e 100644 --- a/Tools/AGSHtml.m +++ b/Tools/AGSHtml.m @@ -774,7 +774,7 @@ static NSMutableSet *textNodes = nil; NSString *text; NSString *val; - text = [children content]; + text = [children escapedContent]; val = [prop objectForKey: @"id"]; if (val == nil) { @@ -847,7 +847,7 @@ static NSMutableSet *textNodes = nil; { if ([t type] == XML_TEXT_NODE) { - NSString *content = [t content]; + NSString *content = [t escapedContent]; if (content == nil) content = @""; str = [str stringByAppendingString: content]; @@ -1182,7 +1182,7 @@ static NSMutableSet *textNodes = nil; NSString *text; NSString *val; - text = [children content]; + text = [children escapedContent]; val = [prop objectForKey: @"id"]; if (val == nil) { @@ -1225,7 +1225,7 @@ static NSMutableSet *textNodes = nil; { if ([t type] == XML_TEXT_NODE) { - NSString *content = [t content]; + NSString *content = [t escapedContent]; if (content == nil) content = @""; str = [str stringByAppendingString: content]; @@ -1340,7 +1340,7 @@ static NSMutableSet *textNodes = nil; { if ([t type] == XML_TEXT_NODE) { - NSString *content = [t content]; + NSString *content = [t escapedContent]; if (content == nil) content = @""; sel = [sel stringByAppendingString: content]; @@ -1366,7 +1366,7 @@ static NSMutableSet *textNodes = nil; { if ([t type] == XML_TEXT_NODE) { - NSString *content = [t content]; + NSString *content = [t escapedContent]; if (content == nil) content = @""; str = [str stringByAppendingString: content]; @@ -2002,7 +2002,7 @@ NSLog(@"Element '%@' not implemented", name); // FIXME { if ([node type] == XML_TEXT_NODE) { - NSString *str = [node content]; + NSString *str = [node escapedContent]; if (str == nil) str = @""; [buf appendString: str]; @@ -2055,7 +2055,7 @@ NSLog(@"Element '%@' not implemented", name); // FIXME [buf appendString: @"
Conforms to:
\n"]; while (node != nil && [[node name] isEqual: @"conform"] == YES) { - NSString *text = [[node firstChild] content]; + NSString *text = [[node firstChild] escapedContent]; if (text == nil) text = @""; [buf appendString: indent]; diff --git a/Tools/autogsdoc.m b/Tools/autogsdoc.m index efd24ec3d..259a3ccf7 100644 --- a/Tools/autogsdoc.m +++ b/Tools/autogsdoc.m @@ -1196,9 +1196,9 @@ main(int argc, char **argv, char **env) AGSIndex *localRefs; parser = [GSXMLParser parserWithContentsOfFile: gsdocfile]; - [parser substituteEntities: NO]; [parser doValidityChecking: YES]; [parser keepBlanks: NO]; + [parser substituteEntities: NO]; if ([parser parse] == NO) { NSLog(@"WARNING %@ is not a valid document", gsdocfile); @@ -1485,9 +1485,9 @@ main(int argc, char **argv, char **env) file, gDate, hDate); } parser = [GSXMLParser parserWithContentsOfFile: gsdocfile]; - [parser substituteEntities: NO]; [parser doValidityChecking: YES]; [parser keepBlanks: NO]; + [parser substituteEntities: NO]; if ([parser parse] == NO) { NSLog(@"WARNING %@ is not a valid document", gsdocfile);