1 #include <stdio.h>
2 #include "windows.h"
3 #include "urlmon.h"
4 #include "libparsifal/parsifal.h"
5
6 #define MAX_URILEN 512
7 XMLCH gbase[MAX_URILEN] = {'\0'}; /* base uri - global for clarity */
8
9 int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts);
10 int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName);
11 int PI(void *UserData, const XMLCH *target, const XMLCH *data);
12 int Characters(void *UserData, const XMLCH *chars, int cbChars);
13 int Comment(void *UserData, const XMLCH *chars, int cbChars);
14 int CharactersWide(void *UserData, const XMLCH *chars, int cbChars);
15 int StartCData(void *UserData);
16 int EndCData(void *UserData);
17 int DoctypeDecl(void *UserData, const XMLCH *name, const XMLCH *publicID, const XMLCH *systemID, int hasInternalSubset);
18 void ErrorHandler(LPXMLPARSER parser);
19 int ResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader);
20 int FreeInputData(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader);
21 int SkippedEntity(void *UserData, const XMLCH *name);
22 int urlstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData);
23 /* see samples/misc/helper.c for comments of the following routines: */
24 size_t GetBaseDir(XMLCH *dst, XMLCH *src);
25 XMLCH *ResolveBaseUri(LPXMLPARSER parser, XMLCH *systemID, XMLCH *base);
26
StartElement(void * UserData,const XMLCH * uri,const XMLCH * localName,const XMLCH * qName,LPXMLVECTOR atts)27 int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts)
28 {
29 if (*uri)
30 printf("\nStart tag: %s uri: %s localName: %s", qName, uri, localName);
31 else
32 printf("\nStart tag: %s", qName);
33
34 if (atts->length) {
35 int i;
36 LPXMLRUNTIMEATT att;
37
38 printf("\nhas %d attributes:", atts->length);
39 for (i=0; i<atts->length; i++) {
40 att = (LPXMLRUNTIMEATT)XMLVector_Get(atts, i);
41
42 if (*att->uri)
43 printf("\n Name: %s Value: %s Prefix: %s LocalName: %s Uri: %s",
44 att->qname, att->value,
45 att->prefix, att->localName,
46 att->uri);
47 else
48 printf("\n Name: %s Value: {%s}",
49 att->qname, att->value);
50 }
51
52 /* this demonstrates XMLParser_GetNamedItem and XML_ABORT, just
53 change the name "findthis" here to abort parsing when
54 this attribute is encountered: */
55
56 if (att = XMLParser_GetNamedItem(UserData, "findthis")) {
57 printf("FOUND ATTRIBUTE %s value: %s\nAborting...\n", att->qname, att->value);
58 return XML_ABORT;
59 }
60 }
61 return 0;
62 }
63
EndElement(void * UserData,const XMLCH * uri,const XMLCH * localName,const XMLCH * qName)64 int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName)
65 {
66 printf("\nEnd tag: %s", qName);
67 return 0;
68 }
69
Characters(void * UserData,const XMLCH * chars,int cbChars)70 int Characters(void *UserData, const XMLCH *chars, int cbChars)
71 {
72 printf("\nText (%d bytes): {", cbChars);
73 for (; cbChars; cbChars--, chars++) putc(*chars, stdout);
74 putc('}', stdout);
75 return 0;
76 }
77
SkippedEntity(void * UserData,const XMLCH * name)78 int SkippedEntity(void *UserData, const XMLCH *name)
79 {
80 printf("\nskipped entity: %s", name);
81 return 0;
82 }
83
DoctypeDecl(void * UserData,const XMLCH * name,const XMLCH * publicID,const XMLCH * systemID,int hasInternalSubset)84 int DoctypeDecl(void *UserData, const XMLCH *name, const XMLCH *publicID, const XMLCH *systemID, int hasInternalSubset)
85 {
86 printf("\nDOCTYPE Name: %s", name);
87 if (publicID) printf(" publicID: %s", publicID);
88 if (systemID) printf(" systemID: %s", systemID);
89 printf(" hasInternalSubset: %d", hasInternalSubset);
90 return 0;
91 }
92
StartCData(void * UserData)93 int StartCData(void *UserData)
94 {
95 printf("\nStart CData tag\n");
96 /* will call Characters to report CDATA contents */
97 return 0;
98 }
99
EndCData(void * UserData)100 int EndCData(void *UserData)
101 {
102 printf("\nEnd CData tag");
103 return 0;
104 }
105
Comment(void * UserData,const XMLCH * chars,int cbChars)106 int Comment(void *UserData, const XMLCH *chars, int cbChars)
107 {
108 printf("\nComment (%d bytes): {", cbChars);
109 for (; cbChars; cbChars--, chars++) putc(*chars, stdout);
110 putc('}', stdout);
111 return 0;
112 }
113
PI(void * UserData,const XMLCH * target,const XMLCH * data)114 int PI(void *UserData, const XMLCH *target, const XMLCH *data)
115 {
116 printf("\nPI tag - target: %s data: %s", target, ((*data) ? data : "no data"));
117 return 0;
118 }
119
ErrorHandler(LPXMLPARSER parser)120 void ErrorHandler(LPXMLPARSER parser)
121 {
122 /* you should treat ERR_XMLP_ABORT as "user error" and give somekind of
123 description before returning from callbacks, otherwise we present parser error: */
124 if (parser->ErrorCode != ERR_XMLP_ABORT) {
125 XMLCH *SystemID = XMLParser_GetSystemID(parser);
126 LPXMLENTITY curEnt = XMLParser_GetCurrentEntity(parser);
127 printf("\nParsing Error: %s\nCode: %d",
128 parser->ErrorString, parser->ErrorCode);
129 if (curEnt && !curEnt->systemID) printf("\nin entity: '%s'", curEnt->name);
130 if (SystemID) printf("\nSystemID: '%s'", SystemID);
131 }
132 printf("\nLine: %d\nColumn: %d", parser->ErrorLine, parser->ErrorColumn);
133 }
134
135 /*
136 Converts UTF-8 string to wchar_t string
137 and shows converted string in MessageBoxW
138
139 Set charactersHandler = CharactersWide if
140 you want to test UTF-8 to wchar_t conversion for
141 text content, you shouldn't run large documents with
142 CharactersWide because those MessageBoxes can get annoying...
143 */
CharactersWide(void * UserData,const XMLCH * chars,int cbChars)144 int CharactersWide(void *UserData, const XMLCH *chars, int cbChars)
145 {
146 wchar_t wstr[1024];
147 int size;
148
149 if (cbChars > 1023) cbChars = 1024;
150
151 if ((size = MultiByteToWideChar(CP_UTF8, 0, chars, cbChars, wstr, 1024))) {
152 *(wstr+size) = L'\0';
153 MessageBoxW(NULL, wstr, L"WinUrl sample", MB_OK);
154 }
155 else {
156 printf("Unicode conversion error!");
157 return XML_ABORT;
158 }
159 return 0;
160 }
161
GetBaseDir(XMLCH * dst,XMLCH * src)162 size_t GetBaseDir(XMLCH *dst, XMLCH *src)
163 {
164 XMLCH *s = strrchr(src, '/');
165 #ifdef _WIN32
166 if (!s) s = strrchr(src, '\\');
167 #endif
168 if (s) {
169 size_t i = (s-src)+1;
170 memcpy(dst, src, i);
171 dst[i] = '\0';
172 return i;
173 }
174 dst[0] = '\0';
175 return 0;
176 }
177
ResolveBaseUri(LPXMLPARSER parser,XMLCH * systemID,XMLCH * base)178 XMLCH *ResolveBaseUri(LPXMLPARSER parser, XMLCH *systemID, XMLCH *base)
179 {
180 XMLCH *s=systemID;
181 for (; *s; s++) {
182 if (*s == ':') return systemID; /* probably absolute */
183 if (*s == '/' || *s == '\\') break;
184 }
185 s = XMLParser_GetPrefixMapping(parser, "xml:base");
186 return (s) ? s : base;
187 }
188
ResolveEntity(void * UserData,LPXMLENTITY entity,LPBUFFEREDISTREAM reader)189 int ResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader)
190 {
191 IStream *pStm = NULL; /* pointer to COM stream */
192 HRESULT hr;
193 XMLCH r[MAX_URILEN];
194 XMLCH *uri = ResolveBaseUri((LPXMLPARSER)UserData, entity->systemID, gbase);
195 if (uri != entity->systemID) {
196 strcpy(r, uri);
197 uri = strcat(r, entity->systemID);
198 }
199 printf("\nLoading external entity: %s uri: %s", entity->name, uri);
200 hr = URLOpenBlockingStream(0, uri, &pStm, 0,0);
201 if (!SUCCEEDED(hr)) {
202 printf("\nError opening url '%s'", uri);
203 if (pStm) pStm->lpVtbl->Release(pStm);
204 return XML_ABORT;
205 }
206
207 reader->inputData = pStm;
208 return 0;
209 }
210
FreeInputData(void * UserData,LPXMLENTITY entity,LPBUFFEREDISTREAM reader)211 int FreeInputData(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader)
212 {
213 IStream *pStm = (IStream*)reader->inputData;
214 if (pStm) pStm->lpVtbl->Release(pStm);
215 return 0;
216 }
217
urlstream(BYTE * buf,int cBytes,int * cBytesActual,void * inputData)218 int urlstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData)
219 {
220 /* calls IStream.Read in C COM way: */
221 HRESULT hr = ((IStream*)inputData)->lpVtbl->Read((IStream*)inputData, buf, cBytes, cBytesActual);
222 return (*cBytesActual < cBytes || !SUCCEEDED(hr));
223 }
224
main(int argc,char * argv[])225 int main(int argc, char* argv[])
226 {
227 LPXMLPARSER parser;
228 IStream *pStm = NULL; /* pointer to COM stream */
229 HRESULT hr;
230 char szUrl[MAX_URILEN];
231
232 printf("\nWINURL Parsifal sample\n\nUrl to parse: ");
233 gets(szUrl);
234
235 /* open the url stream: */
236 hr = URLOpenBlockingStream(0, szUrl, &pStm, 0,0);
237 if (!SUCCEEDED(hr)) {
238 puts("Error opening url!");
239 if (pStm) pStm->lpVtbl->Release(pStm);
240 exit(1);
241 }
242
243 GetBaseDir(gbase, szUrl);
244
245 if (!XMLParser_Create(&parser)) {
246 puts("Error creating parser!");
247 exit(1);
248 }
249
250 parser->startElementHandler = StartElement;
251 parser->endElementHandler = EndElement;
252 parser->charactersHandler = Characters; /* set to CharactersWide
253 to convert UTF-8 -> wchar_t */
254 parser->processingInstructionHandler = PI;
255 parser->commentHandler = Comment;
256 parser->startCDATAHandler = StartCData;
257 parser->endCDATAHandler = EndCData;
258 parser->errorHandler = ErrorHandler;
259 parser->startDTDHandler = DoctypeDecl;
260 parser->skippedEntityHandler = SkippedEntity;
261 parser->resolveEntityHandler = ResolveEntity;
262 parser->externalEntityParsedHandler = FreeInputData;
263 parser->UserData = parser;
264
265 printf("XMLFlags:\n");
266 printf("XMLFLAG_NAMESPACES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_NAMESPACES));
267 printf("XMLFLAG_NAMESPACE_PREFIXES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_NAMESPACE_PREFIXES));
268 printf("XMLFLAG_EXTERNAL_GENERAL_ENTITIES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_EXTERNAL_GENERAL_ENTITIES));
269 printf("XMLFLAG_PRESERVE_GENERAL_ENTITIES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_PRESERVE_GENERAL_ENTITIES));
270 printf("XMLFLAG_UNDEF_GENERAL_ENTITIES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_UNDEF_GENERAL_ENTITIES));
271 printf("XMLFLAG_PRESERVE_WS_ATTRIBUTES: %d\n", _XMLParser_GetFlag(parser,XMLFLAG_PRESERVE_WS_ATTRIBUTES));
272
273 XMLParser_Parse(parser, urlstream, pStm, NULL);
274
275 if (pStm) pStm->lpVtbl->Release(pStm);
276 XMLParser_Free(parser);
277
278 return 0;
279 }
280
281
282