Initial revision
[TestXSLT.git] / XMLParserLibxml.m
1 //
2 //  XMLParserLibxml.m
3 //  TestXSLT
4 //
5 //  Created by Marc Liyanage on Sun Aug 04 2002.
6 //  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "XMLParserLibxml.h"
10
11
12 @implementation XMLParserLibxml
13
14
15 - (id)init {
16
17         if (self = [super init]) {
18
19                 errorMessage = [[NSMutableString alloc] init];
20                 errorLine = 0;
21                 errorOccurred = NO;
22                 xmlContext = NULL;
23                 parsedXmlDoc = NULL;
24                 baseUri = NULL;
25                 
26         }
27
28         return self;
29 }
30
31
32 - (xmlDocPtr)nativeDoc {
33
34         return parsedXmlDoc;
35         
36 }
37
38 - (void)dealloc {
39
40         [errorMessage release];
41
42         if (parsedXmlDoc) {
43                 xmlFreeDoc(parsedXmlDoc);
44         }
45
46         
47 }
48
49
50
51
52 - (void)setErrorMessage:(NSString *)message {
53
54         [errorMessage setString:message];
55
56 }
57
58 - (int)errorLine {
59
60         return errorLine;
61
62 }
63
64 - (NSString *)errorMessage {
65
66         return errorMessage;
67
68 }
69
70
71 - (void)setErrorOccurred:(BOOL)flag {
72
73         errorOccurred = flag;
74         
75 }
76
77 - (void)appendErrorMessage:(NSString *)message {
78
79         if ([errorMessage length] > 0) {
80                 [errorMessage appendString:@"\n"];
81         }
82         [errorMessage appendString:[message substringWithRange:NSMakeRange(0, [message length] - 1)]];
83         [self setErrorOccurred:YES];
84
85 }
86
87 - (BOOL)errorOccurred {
88
89         return errorOccurred;
90
91 }
92
93
94 - (void)setError:(NSString *)message atLine:(int)line {
95
96         [self setErrorMessage:message];
97         errorLine = line;
98         [self setErrorOccurred:YES];
99         
100
101 }
102
103
104 - (void)clearError {
105
106         [errorMessage setString:@""];
107         [self setErrorOccurred:NO];
108         errorLine = 0;
109
110 }
111
112
113 void makeUnixLineFeeds(char *buffer) {
114
115         int i = 0;
116
117         while (buffer[i] != '\0') {
118
119                 if (buffer[i] == '\r') {
120                         if (buffer[i + 1] == '\n') {
121                                 i++;
122                         } else {
123                                 buffer[i] = '\n';
124                         }
125                 }
126                 i++;
127         }
128         
129 }
130
131
132 - (BOOL)checkWellFormedString:(NSString *)xmlCode {
133
134         char *xmlString = (char *)[xmlCode cString];
135         //const char *xmlString = [stringData bytes];
136         int error = 0;
137
138         makeUnixLineFeeds(xmlString);
139         
140         /*
141         NSData *stringData = [xmlCode dataUsingEncoding:NSUTF8StringEncoding];
142         NSData *stringData = [xmlCode dataUsingEncoding:NSISOLatin1StringEncoding];
143
144
145          xmlString = malloc([stringData length] + 1);
146         [stringData getBytes:xmlString];
147         xmlString[[stringData length]] = '\0';
148          */
149                 
150
151         xmlContext = xmlCreateDocParserCtxt(xmlString);
152         
153         if (!xmlContext) {
154                 return NO;
155         }
156
157
158         [self clearError];
159         xmlSetGenericErrorFunc(self, (xmlGenericErrorFunc)XMLParserLibxml_xmlErrorHandler);
160
161         error = xmlParseDocument(xmlContext);
162
163         if (xmlContext->myDoc) {
164                 xmlFreeDoc(xmlContext->myDoc);
165         }
166
167         xmlFreeParserCtxt(xmlContext);
168         xmlContext = NULL;
169
170         if (error != XML_ERR_OK) {
171                 return NO;
172         } else {
173                 [self clearError];
174                 return YES;
175         }
176
177
178 }
179
180
181
182
183 - (BOOL)parseString:(NSString *)xmlCode {
184
185         char *xmlString = (char *)[xmlCode cString];
186         int error = 0;
187
188         makeUnixLineFeeds(xmlString);
189
190         xmlContext = xmlCreateDocParserCtxt(xmlString);
191
192     xmlSubstituteEntitiesDefault(1);
193         xmlLoadExtDtdDefaultValue = 1;
194
195         if (!xmlContext) {
196                 return NO;
197         }
198
199
200         [self clearError];
201         xmlSetGenericErrorFunc(self, (xmlGenericErrorFunc)XMLParserLibxml_xmlErrorHandler);
202
203         error = xmlParseDocument(xmlContext);
204
205
206         if (parsedXmlDoc) {
207                 xmlFreeDoc(parsedXmlDoc);
208         }
209
210         parsedXmlDoc = xmlContext->myDoc;
211
212         
213         xmlFreeParserCtxt(xmlContext);
214         xmlContext = NULL;
215
216         if (error != XML_ERR_OK) {
217                 return NO;
218         }
219
220         if ([self baseUri] != nil) {
221                 xmlNodeSetBase((xmlNodePtr)parsedXmlDoc, (xmlChar *)[[self baseUri] cString]);
222         }
223         [self clearError];
224         return YES;
225
226                 
227 }
228
229
230
231 - (void)markFirstErrorLine {
232
233         if (errorLine == 0 && xmlContext && xmlContext->input) {
234                 errorLine = xmlContext->input->line;
235         }
236
237         
238 }
239
240 void XMLParserLibxml_xmlErrorHandler(id self, const char *message, ...) {
241
242         char *messageData;
243         va_list args;
244
245
246         
247         [self markFirstErrorLine];
248
249         /* we're only interested in messages with the format string "%s" */
250         if (strcmp(message, "%s")) {
251                 return;
252         }
253
254         va_start(args, message);
255         messageData = va_arg(args, char *);
256
257         [self appendErrorMessage:[NSString stringWithCString:messageData]];
258
259     va_end(args);
260
261
262 }
263
264
265 void XMLParserLibxml_xmlErrorHandler2(id self, const char *message, ...) {
266
267         const char *end = message + (strlen(message) - 1);
268         char *pos = (char *)message;
269         int errorLine = 0;
270         NSString *errorMessage;
271         char completeMessage[512];
272         va_list args;
273
274         /*      Do not overwrite previous error information so the
275                 first error in a series will be preserved
276                 */
277         if ([self errorOccurred]) {
278                 return;
279         }
280
281 //      NSLog(@"xml error handler: %s", message);
282
283         va_start(args, message);
284
285         while (pos <= end) {
286
287                 if (!strncmp(pos, "%s", 2)) {
288                         va_arg(args, char *);
289                 } else if (!strncmp(pos, "%d", 2)) {
290                         errorLine = va_arg(args, int);
291                 }
292
293                 pos++;
294
295         }
296
297     va_end(args);
298
299         va_start(args, message);
300         vsnprintf(completeMessage, 512, message, args);
301     va_end(args);
302
303         errorMessage = [NSString stringWithCString:completeMessage];
304         [self setError:errorMessage atLine:errorLine];
305
306
307 }
308
309
310 - (void)setBaseUri:(NSString *)uri {
311
312         [uri retain];
313         [baseUri release];
314         baseUri = uri;
315 }
316
317 - (NSString *)baseUri {
318         return baseUri;
319 }
320
321
322
323 @end