Annotation of libwww/Library/src/HTRDF.c, revision 2.4
2.1 frystyk 1: /*
2: ** RDF PARSER
3: **
2.4 ! barstow 4: ** @(#) $Id: HTRDF.c,v 2.3 1999/05/05 18:41:49 frystyk Exp $
2.1 frystyk 5: **
6: ** Copyright © 1995-1998 World Wide Web Consortium, (Massachusetts
7: ** Institute of Technology, Institut National de Recherche en
8: ** Informatique et en Automatique, Keio University). All Rights
9: ** Reserved. This program is distributed under the W3C's Software
10: ** Intellectual Property License. This program is distributed in the hope
11: ** that it will be useful, but WITHOUT ANY WARRANTY; without even the
12: ** implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13: ** PURPOSE. See W3C License http://www.w3.org/Consortium/Legal/ for more
14: ** details.
15: **
16: ** This module requires expat
17: **
18: ** AUTHOR:
19: ** John Punin <puninj@cs.rpi.edu>,
20: ** Henrik
21: */
22:
23: #include "WWWLib.h"
24: #include "WWWInit.h"
25: #include "WWWXML.h"
26: #include "HTRDF.h"
27:
28: struct _HTStream {
29: const HTStreamClass * isa;
30: int state;
31: HTRequest * request;
32: HTStream * target;
33: HTRDF * rdfparser;
34: };
35:
36: #define PUTC(t,c) (*(t)->target->isa->put_character)((t)->target, (c))
37: #define PUTS(t,s) (*(t)->target->isa->put_string)((t)->target, (s))
38:
39: struct _HTTriple {
2.3 frystyk 40: char * m_sPredicate;
41: char * m_sSubject;
42: char * m_sObject;
2.1 frystyk 43: };
44:
45: struct _HTElement {
2.3 frystyk 46: char * m_sName;
2.1 frystyk 47: HTAssocList * m_attributes;
48: HTList * m_children;
2.3 frystyk 49: char * m_sID;
50: char * m_sBagID;
2.1 frystyk 51: HTList * m_vTargets;
52: BOOL m_bDone;
2.3 frystyk 53: char * m_sPrefix;
54: char * m_sContent;
2.1 frystyk 55: };
56:
57: struct _HTRDFParser {
58: HTList * m_namespaceStack;
59: HTList * m_elementStack;
60: HTElement * m_root;
61: HTList * m_triples;
2.3 frystyk 62: char * m_sSource;
2.1 frystyk 63: HTList * m_vAllNameSpaces;
64:
65: BOOL m_bCreateBags;
66: BOOL m_bFetchSchemas;
67:
68: HTList * m_parseTypeStack;
69: HTList * m_parseElementStack;
2.3 frystyk 70: char * m_sLiteral;
2.1 frystyk 71:
72: HTList * m_vResources;
73: HTList * m_vResolveQueue;
74: HTHashtable * m_hIDtable;
75: int m_iReificationCounter;
76:
77: HTStream * ostream;
78:
79: HTTripleCallback_new * newTripleInstance;
80: void * tripleContext;
81: };
82:
83: /* @@@ Should not be global but controlled by name spaces @@@ */
84: PRIVATE HTRDFCallback_new * RDFInstance = NULL;
85: PRIVATE void * RDFInstanceContext = NULL;
86:
2.3 frystyk 87: PRIVATE char * HTRDF_processContainer (HTRDF *me, HTElement *e);
88: PRIVATE char * HTRDF_processPredicate (HTRDF *me, HTElement *predicate,
2.1 frystyk 89: HTElement *description,
2.3 frystyk 90: char * sTarget,
2.1 frystyk 91: BOOL reificate);
2.3 frystyk 92: PRIVATE void HTRDF_processListItem (HTRDF *me,char * sID, HTElement *listitem,
2.1 frystyk 93: int iCounter);
94: PRIVATE void HTRDF_checkAttributes (HTRDF *me,HTElement *Element);
95: PRIVATE BOOL HTRDF_expandAttributes (HTRDF *me, HTElement *parent, HTElement *ele);
2.3 frystyk 96: PRIVATE char * HTRDF_reificate (HTRDF *me, char * sPredicate, char * sSubject,
97: char * sObject, char * sNodeID);
2.4 ! barstow 98: /* ------------------------------------------------------------------------- */
! 99:
! 100: /*
! 101: ** Append the markup for the given element and its attribute to the
! 102: ** parser's "Literal" buffer. This buffer is filled in when parseType="Literal".
! 103: */
! 104: PRIVATE void addMarkupStart (HTRDF *rdfp, const char *name, const char **atts)
! 105: {
! 106: int i=0;
! 107:
! 108: if (!rdfp || !name) return;
! 109:
! 110: StrAllocCat(rdfp->m_sLiteral, "<");
! 111: StrAllocCat(rdfp->m_sLiteral, name);
! 112:
! 113: while (atts[i]) {
! 114: StrAllocCat(rdfp->m_sLiteral, " ");
! 115: StrAllocCat(rdfp->m_sLiteral, atts[i]);
! 116: StrAllocCat(rdfp->m_sLiteral, "=\"");
! 117: StrAllocCat(rdfp->m_sLiteral, atts[i+1]);
! 118: StrAllocCat(rdfp->m_sLiteral, "\"");
! 119: i+=2;
! 120: }
! 121:
! 122: StrAllocCat(rdfp->m_sLiteral, ">");
! 123: }
! 124:
! 125: /*
! 126: ** Terminate this element's "Literal" buffer. This buffer is filled in when
! 127: ** parseType="Literal".
! 128: */
! 129: PRIVATE void addMarkupEnd (HTRDF *rdfp, const char *name)
! 130: {
! 131: if (!rdfp || !name) return;
! 132:
! 133: StrAllocCat(rdfp->m_sLiteral, "</");
! 134: StrAllocCat(rdfp->m_sLiteral, name);
! 135: StrAllocCat(rdfp->m_sLiteral, ">");
! 136: }
2.1 frystyk 137:
138: /* ------------------------------------------------------------------------- */
139:
140: /*
141: ** Searches a whole list of Strings and returns true if the String is found.
142: */
2.3 frystyk 143: PRIVATE BOOL HTList_contains (HTList *list, char * s)
2.1 frystyk 144: {
145: HTList *cur = list;
2.3 frystyk 146: char * cs = NULL;
147: while ((cs = (char *) HTList_nextObject(cur))) {
2.1 frystyk 148: if (!strcmp(cs, s)) return YES;
149: }
150: return NO;
151: }
152:
153: /*
154: ** Useful function that Trims a string
155: ** @@@ Should use HTStrip() @@@
156: */
157: PRIVATE char * trim (char *s)
158: {
159: char *p = NULL, *t = NULL;
160: int len = s ? strlen(s) : -1;
161: if (s && len > 0) {
162: StrAllocCopy(t, s);
163: p = &(s[len-1]);
164: while(p!=s) {
165: if (!isspace((int)(*p)))
166: break;
167: p--;
168: }
169: t[(int)(p-s)+1] = '\0';
170: if (isspace((int) t[(int)(p-s)]))
171: t[(int)(p-s)] = '\0';
172: }
173: return t;
174: }
175:
176: /* ------------------------------------------------------------------------- */
177: /* TRIPLE of RDF */
178: /* ------------------------------------------------------------------------- */
179:
2.3 frystyk 180: PUBLIC HTTriple * HTTriple_new (char * p, char * s, char * o)
2.1 frystyk 181: {
182: HTTriple * me = NULL;
183: if (p && s && o) {
184: if ((me = (HTTriple *) HT_CALLOC(1, sizeof(HTTriple))) == NULL)
185: HT_OUTOFMEM("HTTriple_new");
186: StrAllocCopy(me->m_sPredicate, p);
187: StrAllocCopy(me->m_sSubject, s);
188: StrAllocCopy(me->m_sObject, o);
189: }
190: return me;
191: }
192:
193: PUBLIC BOOL HTTriple_delete (HTTriple * me)
194: {
195: if (me) {
196: HT_FREE(me->m_sPredicate);
197: HT_FREE(me->m_sSubject);
198: HT_FREE(me->m_sObject);
199: HT_FREE(me);
200: return YES;
201: }
202: return NO;
203: }
204:
205: PUBLIC void HTTriple_print (HTTriple * me)
206: {
207: if (me)
208: HTPrint("TRIPLE(%s,%s,%s)\n", me->m_sPredicate, me->m_sSubject,
209: me->m_sObject);
210: }
211:
2.3 frystyk 212: PUBLIC char * HTTriple_subject (HTTriple * me)
2.1 frystyk 213: {
214: return me ? me->m_sSubject : NULL;
215: }
216:
2.3 frystyk 217: PUBLIC char * HTTriple_predicate (HTTriple * me)
2.1 frystyk 218: {
219: return me ? me->m_sPredicate : NULL;
220: }
221:
2.3 frystyk 222: PUBLIC char * HTTriple_object (HTTriple * me)
2.1 frystyk 223: {
224: return me ? me->m_sObject : NULL;
225: }
226:
227: /* ------------------------------------------------------------------------- */
228: /* ELEMENT of RDF */
229: /* ------------------------------------------------------------------------- */
230:
2.3 frystyk 231: PUBLIC HTElement * HTElement_new (char * sName, HTAssocList * al)
2.1 frystyk 232: {
233: HTElement * me = NULL;
234: if (sName) {
235: if ((me = (HTElement *) HT_CALLOC(1, sizeof(HTElement))) == NULL)
236: HT_OUTOFMEM("HTElement_new");
237: StrAllocCopy(me->m_sName, sName);
238: me->m_attributes = al ? al : HTAssocList_new();
239: me->m_children = HTList_new();
240: /*me->m_nodes = HTAssocList_new();*/ /* Sirpac does not use nodes list */
241: me->m_vTargets = HTList_new();
242: me->m_bDone = FALSE;
243: }
244: return me;
245: }
246:
247: /*
248: ** Creates a Data Element and saves the data in the Content field.
249: ** Data Element does not have attributes
250: */
2.3 frystyk 251: PUBLIC HTElement * HTElement_new2 (char * sContent)
2.1 frystyk 252: {
253: HTElement * me = NULL;
254: if (sContent) {
255: if ((me = (HTElement *) HT_CALLOC(1, sizeof(HTElement))) == NULL)
256: HT_OUTOFMEM("HTElement_new2");
257: StrAllocMCopy(&me->m_sName, "[DATA: ", sContent, "]", NULL);
258: me->m_attributes = NULL;
259: me->m_children = HTList_new();
260: /*me->m_nodes = HTAssocList_new();*/
261: me->m_vTargets = HTList_new();
262: me->m_bDone = FALSE;
263: StrAllocCopy(me->m_sContent, sContent);
264: }
265: return me;
266: }
267:
2.3 frystyk 268: PUBLIC BOOL HTElement_addData (HTElement *me, char * sContent)
2.1 frystyk 269: {
270: if (me && sContent) {
271: int l = strlen(me->m_sName);
272: StrAllocCat(me->m_sContent, sContent);
273: me->m_sName[l-1]='\0';
274: StrAllocMCat(&me->m_sName, sContent, "]", NULL);
275: return YES;
276: }
277: return NO;
278: }
279:
280: PUBLIC BOOL HTElement_delete (HTElement * me)
281: {
282: if (me) {
283: HT_FREE(me->m_sName);
284: if (me->m_attributes) HTAssocList_delete(me->m_attributes);
285: if (me->m_children) HTList_delete(me->m_children);
286: HT_FREE(me->m_sID);
287: HT_FREE(me->m_sBagID);
288: if (me->m_vTargets) HTList_delete(me->m_vTargets);
289: HT_FREE(me->m_sPrefix);
290: HT_FREE(me->m_sContent);
291: HT_FREE(me);
292: return YES;
293: }
294: return NO;
295: }
296:
297: PUBLIC BOOL HTElement_addChild (HTElement * me, HTElement * element)
298: {
299: return (me && element) ? HTList_appendObject(me->m_children, element) : NO;
300: }
301:
2.3 frystyk 302: PUBLIC BOOL HTElement_addAttribute (HTElement * me, char * sName, char * sValue)
2.1 frystyk 303: {
304: return (me && sName && sValue) ?
305: HTAssocList_addObject(me->m_attributes, sName, sValue) : NO;
306: }
307:
2.3 frystyk 308: PUBLIC BOOL HTElement_removeAttribute (HTElement * me, char * sName)
2.1 frystyk 309: {
310: return (me && sName) ? HTAssocList_removeObject(me->m_attributes, sName) : NO;
311: }
312:
2.3 frystyk 313: PUBLIC char * HTElement_getAttribute (HTElement * me, char * sName)
2.1 frystyk 314: {
315: return (me && sName) ? HTAssocList_findObjectCaseSensitiveExact(me->m_attributes, sName) : NULL;
316: }
317:
2.3 frystyk 318: PUBLIC char * HTElement_getAttribute2 (HTElement * me, char * sNamespace, char * sName)
2.1 frystyk 319: {
2.3 frystyk 320: char * fValue = NULL;
321: char * fName = NULL;
2.1 frystyk 322: if (me && sNamespace && sName) {
323: StrAllocMCopy(&fName, sNamespace, sName, NULL);
324: fValue = HTAssocList_findObjectCaseSensitiveExact(me->m_attributes, fName);
325: HT_FREE(fName);
326: }
327: return fValue;
328: }
329:
330: PUBLIC BOOL HTElement_addTarget (HTElement * me, HTElement * element)
331: {
332: return (me && element) ? HTList_addObject(me->m_vTargets, element) : NO;
333: }
334:
335: PUBLIC HTElement * HTElement_target (HTElement * me)
336: {
337: return me ? (HTElement *) HTList_lastObject(me->m_vTargets) : NULL;
338: }
339:
340: PUBLIC BOOL HTElement_instanceOfData (HTElement * me)
341: {
342: return (me && me->m_sContent) ? YES : NO;
343: }
344:
345: /* ------------------------------------------------------------------------- */
346: /* EXPAT HANDLERS */
347: /* ------------------------------------------------------------------------- */
348:
349: /*
350: * Called for each new element.
351: * Build up the document tree using an element stack
352: */
353: PRIVATE void XML_startElement (void * userData,
354: const XML_Char * name, const XML_Char ** atts)
355: {
356: HTRDF * rdfp = (HTRDF *) userData;
357: HTAssocList * namespaces = HTAssocList_new();
358: HTAssocList * newAL = HTAssocList_new();
359: int i = 0;
360: /**
361: * The following loop tries to identify special xmlns prefix
362: * attributes and update the namespace stack accordingly.
363: * While doing all this, it builds another AttributeList instance
364: * which will hold the expanded names of the attributes
365: * (I think this approach is only useful for RDF which uses
366: * attributes as an abbreviated syntax for element names)
367: */
368: if (atts) {
369: while (atts[i]) {
2.3 frystyk 370: char * aName = (char * ) atts[i];
2.1 frystyk 371: if (!strcmp(aName, "xmlns")) {
2.3 frystyk 372: char * aValue = (char *) atts[i+1];
2.1 frystyk 373: int len = aValue ? strlen(aValue) : -1;
374: if (len == 0 && !rdfp->m_sSource)
375: aValue = rdfp->m_sSource;
376: HTAssocList_addObject(namespaces, aName, aValue);
377: /* save all non-RDF schema addresses */
378: if (!HTList_contains(rdfp->m_vAllNameSpaces, aValue) &&
379: strncmp(aValue, RDFMS, strlen(RDFMS)) &&
380: strncmp(aValue, RDFSCHEMA, strlen(RDFSCHEMA))) {
2.3 frystyk 381: char * nname = NULL;
2.1 frystyk 382: StrAllocCopy(nname, aValue);
383: HTList_addObject(rdfp->m_vAllNameSpaces, nname);
384: }
385:
386: /* Special case: Don't save document's own address */
387: if (rdfp->m_sSource &&
388: !strncmp(aValue, rdfp->m_sSource, strlen(rdfp->m_sSource))) {
2.3 frystyk 389: char * nname = NULL;
2.1 frystyk 390: StrAllocCopy(nname, aValue);
391: HTList_addObject(rdfp->m_vAllNameSpaces, nname);
392: }
393: } else if (!strncmp(aName, "xmlns:", 6)) {
2.3 frystyk 394: char * aValue = (char *) atts[i+1];
395: char * nName = NULL;
2.1 frystyk 396: int len = aValue ? strlen(aValue) : -1;
397: if (len == 0 && !rdfp->m_sSource)
398: aValue = rdfp->m_sSource;
399: StrAllocCopy(nName, &(aName[6]));
400: HTAssocList_addObject(namespaces, nName, aValue);
401: HT_FREE(nName);
402:
403: /* Save all non-RDF schema addresses */
404: if (!HTList_contains(rdfp->m_vAllNameSpaces, aValue) &&
405: strncmp(aValue, RDFMS, strlen(RDFMS)) &&
406: strncmp(aValue, RDFSCHEMA, strlen(RDFSCHEMA))) {
2.3 frystyk 407: char * nname = NULL;
2.1 frystyk 408: StrAllocCopy(nname, aValue);
409: HTList_addObject(rdfp->m_vAllNameSpaces, nname);
410: }
411:
412: /* Special case: Don't save document's own address */
413: if (rdfp->m_sSource &&
414: !strncmp(aValue, rdfp->m_sSource, strlen(rdfp->m_sSource))) {
2.3 frystyk 415: char * nname = NULL;
2.1 frystyk 416: StrAllocCopy(nname, aValue);
417: HTList_addObject(rdfp->m_vAllNameSpaces, nname);
418: }
419: }
420: i+=2;
421: } /* end of while */
422: } /* end of if */
423:
424: /*
425: ** Place new namespace declarations into the stack
426: ** (Yes, I could optimize this a bit, not it wastes space
427: ** if there are no xmlns definitions)
428: */
429: HTList_addObject(rdfp->m_namespaceStack, namespaces);
430:
431: /*
432: ** Figure out the prefix part if it exists and
433: ** determine the namespace of the element accordingly
434: */
435: {
2.3 frystyk 436: char * sNamespace = NULL;
437: char * sElementName = NULL;
438: char * sPrefix2 = NULL;
2.1 frystyk 439: HTElement *newElement = NULL;
440: char *pindex = strchr(name, ':');
441: int ix = pindex ? (int) (pindex - name) : -1 ;
442: if (ix > 0) {
443: if (!(sPrefix2 = HT_MALLOC(ix+1)))
444: HT_OUTOFMEM("XML_startELement");
445: strncpy(sPrefix2, name, ix);
446: sPrefix2[ix]='\0';
447: sNamespace = HTRDF_namespace(rdfp, sPrefix2);
448: StrAllocCopy(sElementName, &(name[ix+1]));
449: HT_FREE(sPrefix2);
450: } else {
451: sNamespace = HTRDF_namespace(rdfp, "xmlns");
452: StrAllocCopy(sElementName, name);
453: }
454:
455: /*
456: * Finally look for attributes other than the special xmlns,
457: * expand them, and place to the new Attribute List
458: */
459: i = 0;
460: if (atts) {
461: while (atts[i]) {
2.3 frystyk 462: char * aName = (char *) atts[i];
463: char * sAttributeNamespace = NULL;
2.1 frystyk 464: if (strncmp(aName, "xmlns", 5)) {
2.3 frystyk 465: char * aValue = (char *) atts[i+1];
466: char * sPrefix = NULL;
2.1 frystyk 467: /* Expat does not have type for attributes */
468: pindex = strchr(aName, ':');
469: ix = pindex ? (int) (pindex - aName) : -1;
470: if (ix > 0) {
471: if (!(sPrefix = HT_MALLOC(ix+1)))
472: HT_OUTOFMEM("XML_startELement");
473: strncpy(sPrefix, aName, ix);
474: sPrefix[ix] = '\0';
475: sAttributeNamespace = HTRDF_namespace(rdfp, sPrefix);
476: aName = &(aName[ix+1]);
477: HT_FREE(sPrefix);
478: } else {
479: if (!sNamespace)
480: sAttributeNamespace = HTRDF_namespace(rdfp, "xmlns");
481: else
482: StrAllocCopy(sAttributeNamespace, sNamespace);
483: }
484:
485: if (HTRDF_parseLiteral(rdfp)) {
486: if (!sPrefix) {
487: if (!(sPrefix = HT_MALLOC(8)))
488: HT_OUTOFMEM("XML_startELement");
489: sprintf(sPrefix, "gen%d\n", i);
490: }
491: {
2.3 frystyk 492: char * fName = NULL;
2.1 frystyk 493: StrAllocMCopy(&fName, sPrefix, ":", aValue, NULL);
494: HTAssocList_addObject(newAL, fName, aValue);
495: HT_FREE(fName);
496: StrAllocMCopy(&fName, "xmlns:", sPrefix, NULL);
497: HTAssocList_addObject(newAL, fName, sAttributeNamespace);
498: HT_FREE(fName);
499: }
500: } else {
2.3 frystyk 501: char * fName = NULL;
2.1 frystyk 502: StrAllocMCopy(&fName, sAttributeNamespace, aName, NULL);
503: HTAssocList_addObject(newAL, fName, aValue);
504: HT_FREE(fName);
505: }
506:
507: HT_FREE(sAttributeNamespace);
508:
509: /*
510: ** This call will try to see if the user is using
511: ** RDF look-alike elements from another namespace
512: **
513: ** Note: you can remove the call if you wish
514: */
515: #if 0
516: HTRDF_likeRDF (rdfp, sAttributeNamespace, aName);
517: #endif
518:
519: } /* end of if */
520: i+=2;
521: } /* end of while */
522: } /* end of if atts */
523:
524: /*
525: * If we have parseType="Literal" set earlier, this element
526: * needs some additional attributes to make it stand-alone
527: * piece of XML
528: */
529: if (HTRDF_parseLiteral(rdfp)) {
2.3 frystyk 530: char * fName = NULL;
2.4 ! barstow 531:
2.1 frystyk 532: if (!sPrefix2) {
533: if (sNamespace)
534: HTAssocList_addObject(newAL, "xmlns:gen", sNamespace);
535: StrAllocMCopy(&fName, "gen", sElementName, NULL);
536: newElement = HTElement_new(fName, newAL);
537: StrAllocCopy(newElement->m_sPrefix, "gen");
538: HT_FREE(fName);
539: } else {
2.3 frystyk 540: char * sAttributeNamespace = HTRDF_namespace(rdfp, sPrefix2);
2.1 frystyk 541: if (sAttributeNamespace) {
542: StrAllocMCopy(&fName, "xmlns:", sPrefix2, NULL);
543: HTAssocList_addObject(newAL, fName, sAttributeNamespace);
544: HT_FREE(fName);
545: }
546: StrAllocMCopy(&fName, sPrefix2, ":", sElementName, NULL);
547: newElement = HTElement_new(fName, newAL);
548: HT_FREE(fName);
549: }
550: } else {
2.3 frystyk 551: char * fName = NULL;
2.1 frystyk 552: StrAllocMCopy(&fName, sNamespace, sElementName, NULL);
553: newElement = HTElement_new(fName, newAL);
554: HT_FREE(fName);
555: /* HTRDF_likeRDF (rdfp, sNamespace, sElementName); */
556: }
557: HT_FREE(sElementName);
558: HT_FREE(sNamespace);
559: HTRDF_checkAttributes(rdfp, newElement);
2.4 ! barstow 560:
2.1 frystyk 561: /*
562: ** Check parseType
563: */
564: {
2.3 frystyk 565: char * fName = NULL;
566: char * sLiteralValue = NULL;
2.1 frystyk 567: StrAllocMCopy(&fName, RDFMS, "parseType", NULL);
568: sLiteralValue = HTElement_getAttribute(newElement, fName);
569: HT_FREE(fName);
570: if (sLiteralValue && strcmp(sLiteralValue, "Resource")) {
571: /**
572: * This is the management of the element where
573: * parseType="Literal" appears
574: *
575: * You should notice RDF V1.0 conforming implementations
576: * must treat other values than Literal and Resource as
577: * Literal. This is why the condition is !equals("Resource")
578: */
579:
580: HTList_addObject(rdfp->m_parseTypeStack, sLiteralValue);
581: if (!HTList_isEmpty(rdfp->m_elementStack)) {
582: HTElement *e = (HTElement *)
583: HTList_lastObject(rdfp->m_elementStack);
584: HTElement_addChild(e, newElement);
585: }
586: HTList_addObject(rdfp->m_elementStack, newElement);
587: HTList_addObject(rdfp->m_parseElementStack, newElement);
588: HT_FREE(rdfp->m_sLiteral);
589: StrAllocCopy(rdfp->m_sLiteral, "");
590: return;
591: }
592:
593: if (HTRDF_parseLiteral(rdfp)) {
594: /*
595: * This is the management of any element nested within
596: * a parseType="Literal" declaration
597: */
2.4 ! barstow 598: /* Add the element to the parser's literal buffer */
! 599: addMarkupStart (rdfp, name, atts);
! 600:
2.1 frystyk 601: HTList_addObject(rdfp->m_elementStack, newElement);
602: return;
603: }
604:
605: /*
606: ** Update the containment hierarchy with the stack.
607: */
608: if (!HTList_isEmpty(rdfp->m_elementStack)) {
609: HTElement *e = (HTElement *)
610: HTList_lastObject(rdfp->m_elementStack);
611: HTElement_addChild(e, newElement);
612: }
613:
614: /*
615: ** Place the new element into the stack
616: */
617: HTList_addObject(rdfp->m_elementStack, newElement);
618: if (sLiteralValue && !strcmp(sLiteralValue, "Resource")) {
619: HTList_addObject(rdfp->m_parseTypeStack, sLiteralValue);
620: HTList_addObject(rdfp->m_parseElementStack, newElement);
621: HT_FREE(rdfp->m_sLiteral);
622: StrAllocCopy(rdfp->m_sLiteral, "");
623:
624: /*
625: * Since parseType="Resource" implies the following
626: * production must match Description, let's create
627: * an additional Description node here in the document tree.
628: */
629: {
2.3 frystyk 630: char * fName = NULL;
2.1 frystyk 631: HTElement *desc = NULL;
632: HTAssocList * al = HTAssocList_new ();
633: StrAllocMCopy(&fName, RDFMS, "Description", NULL);
634: desc = HTElement_new(fName, al);
635: HT_FREE(fName);
636: if (!HTList_isEmpty(rdfp->m_elementStack)) {
637: HTElement *e = (HTElement *)
638: HTList_lastObject(rdfp->m_elementStack);
639: HTElement_addChild(e, desc);
640: }
641: HTList_addObject(rdfp->m_elementStack, desc);
642: }
643: } /* end of if */
644: } /* end of block */
645: } /* end of block */
646: }
647:
648: /*
649: * For each end of an element scope step back in the
650: * element and namespace stack
651: */
652: PRIVATE void XML_endElement (void * userData,
653: const XML_Char * name)
654: {
655: HTRDF * rdfp = (HTRDF *) userData;
656: BOOL bParseLiteral = rdfp ? HTRDF_parseLiteral(rdfp) : NO;
657: HTAssocList * namespaces = HTList_removeLastObject(rdfp->m_namespaceStack);
658: rdfp->m_root = (HTElement *) HTList_removeLastObject(rdfp->m_elementStack);
659: if (namespaces) HTAssocList_delete(namespaces);
660:
661: if (bParseLiteral) {
662: HTElement *pe = (HTElement *)
663: HTList_lastObject(rdfp->m_parseElementStack);
664: if (pe != rdfp->m_root) {
2.4 ! barstow 665: /* Terminate the literal */
! 666: addMarkupEnd (rdfp, name);
2.1 frystyk 667: } else {
668: HTElement *de = HTElement_new2(rdfp->m_sLiteral);
669: HTElement_addChild(pe, de);
2.4 ! barstow 670:
2.1 frystyk 671: HT_FREE(rdfp->m_sLiteral);
672: StrAllocCopy(rdfp->m_sLiteral, "");
673: HTList_removeLastObject(rdfp->m_parseElementStack);
674: HTList_removeLastObject(rdfp->m_parseTypeStack);
675: }
676: } else if (HTRDF_parseResource(rdfp)) {
677: /**
678: * If we are doing parseType="Resource"
679: * we need to explore whether the next element in
680: * the stack is the closing element in which case
681: * we remove it as well (remember, there's an
682: * extra Description element to be removed)
683: */
684: if (!HTList_isEmpty(rdfp->m_elementStack)) {
685: HTElement *pe = (HTElement *)
686: HTList_lastObject(rdfp->m_parseElementStack);
687: HTElement *e = (HTElement *)
688: HTList_lastObject(rdfp->m_elementStack);
689: if (pe == e) {
690: e = (HTElement *) HTList_removeLastObject(rdfp->m_elementStack);
691: HTList_removeLastObject(rdfp->m_parseElementStack);
692: HTList_removeLastObject(rdfp->m_parseTypeStack);
693: }
694: }
695: }
696: }
697:
698: PRIVATE void XML_characterData (void * userData,
699: const XML_Char * s, int len)
700: {
701: /*
702: * Place all characters as Data instance to the containment
703: * hierarchy with the help of the stack.
704: */
705: HTRDF * rdfp = (HTRDF *) userData;
2.3 frystyk 706: HTElement * e = (HTElement *) HTList_lastObject(rdfp->m_elementStack);
707: char * tstr = NULL;
708: char * str = NULL;
709: if (!(str = (char *) HT_MALLOC(len+1)))
2.1 frystyk 710: HT_OUTOFMEM("XML_characterData");
711: strncpy(str, s, len);
712: str[len]='\0';
713: if (HTRDF_parseLiteral(rdfp)) {
714: StrAllocCat(rdfp->m_sLiteral, str);
715: HT_FREE(str);
716: return;
717: }
718: /* JUST FOR EXPAT */
719: {
720: HTElement *lch = (HTElement *) HTList_lastObject(e->m_children);
721: if (lch && HTElement_instanceOfData(lch)) {
722: HTElement_addData(lch, str);
723: HT_FREE(str);
724: return;
725: }
726: }
727: /*
728: * Warning: this is not correct procedure according to XML spec.
729: * All whitespace matters!
730: */
731: tstr = trim(str);
732: if (strlen(tstr) > 0) {
733: HTElement * de = HTElement_new2(tstr);
734: HTElement_addChild(e, de);
735: }
736: HT_FREE(str); HT_FREE(tstr);
737: }
738:
739: PRIVATE void XML_processingInstruction (void * userData,
740: const XML_Char * target,
741: const XML_Char * data)
742: {
743: return;
744: }
745:
746: /*
747: ** This is called for any characters in the XML document for
748: ** which there is no applicable handler. This includes both
749: ** characters that are part of markup which is of a kind that is
750: ** not reported (comments, markup declarations), or characters
751: ** that are part of a construct which could be reported but
752: ** for which no handler has been supplied. The characters are passed
753: ** exactly as they were in the XML document except that
754: ** they will be encoded in UTF-8. Line boundaries are not normalized.
755: ** Note that a byte order mark character is not passed to the default handler.
756: ** If a default handler is set, internal entity references
757: ** are not expanded. There are no guarantees about
758: ** how characters are divided between calls to the default handler:
759: ** for example, a comment might be split between multiple calls.
760: */
761: PRIVATE void XML_default (void * userData,
762: const XML_Char * s, int len)
763: {
764: return;
765: }
766:
767: /*
768: ** This is called for a declaration of an unparsed (NDATA)
769: ** entity. The base argument is whatever was set by XML_SetBase.
770: ** The entityName, systemId and notationName arguments will never be null.
771: ** The other arguments may be.
772: */
773: PRIVATE void XML_unparsedEntityDecl (void * userData,
774: const XML_Char * entityName,
775: const XML_Char * base,
776: const XML_Char * systemId,
777: const XML_Char * publicId,
778: const XML_Char * notationName)
779: {
780: return;
781: }
782:
783: /*
784: ** This is called for a declaration of notation.
785: ** The base argument is whatever was set by XML_SetBase.
786: ** The notationName will never be null. The other arguments can be.
787: */
788: PRIVATE void XML_notationDecl (void * userData,
789: const XML_Char * notationName,
790: const XML_Char * base,
791: const XML_Char * systemId,
792: const XML_Char * publicId)
793: {
794: return;
795: }
796:
797: /*
798: ** This is called for a reference to an external parsed general entity.
799: ** The referenced entity is not automatically parsed.
800: ** The application can parse it immediately or later using
801: ** XML_ExternalEntityParserCreate.
802: ** The parser argument is the parser parsing the entity containing the reference;
803: ** it can be passed as the parser argument to XML_ExternalEntityParserCreate.
804: ** The systemId argument is the system identifier as specified in the entity
805: ** declaration; it will not be null.
806: ** The base argument is the system identifier that should be used as the base for
807: ** resolving systemId if systemId was relative; this is set by XML_SetBase;
808: ** it may be null.
809: ** The publicId argument is the public identifier as specified in the entity declaration,
810: ** or null if none was specified; the whitespace in the public identifier
811: ** will have been normalized as required by the XML spec.
812: ** The openEntityNames argument is a space-separated list of the names of the entities
813: ** that are open for the parse of this entity (including the name of the referenced
814: ** entity); this can be passed as the openEntityNames argument to
815: ** XML_ExternalEntityParserCreate; openEntityNames is valid only until the handler
816: ** returns, so if the referenced entity is to be parsed later, it must be copied.
817: ** The handler should return 0 if processing should not continue because of
818: ** a fatal error in the handling of the external entity.
819: ** In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
820: ** error.
821: ** Note that unlike other handlers the first argument is the parser, not userData.
822: */
823: PRIVATE int XML_externalEntityRef (XML_Parser parser,
824: const XML_Char * openEntityNames,
825: const XML_Char * base,
826: const XML_Char * systemId,
827: const XML_Char * publicId)
828: {
829: return 0;
830: }
831:
832: /*
833: ** This is called for an encoding that is unknown to the parser.
834: ** The encodingHandlerData argument is that which was passed as the
835: ** second argument to XML_SetUnknownEncodingHandler.
836: ** The name argument gives the name of the encoding as specified in
837: ** the encoding declaration.
838: ** If the callback can provide information about the encoding,
839: ** it must fill in the XML_Encoding structure, and return 1.
840: ** Otherwise it must return 0.
841: ** If info does not describe a suitable encoding,
842: ** then the parser will return an XML_UNKNOWN_ENCODING error.
843: */
844: PRIVATE int XML_unknownEncoding (void * encodingHandlerData,
845: const XML_Char * name,
846: XML_Encoding * info)
847: {
848: return 0;
849: }
850:
851: /* ------------------------------------------------------------------------- */
852: /* HTXML STREAM HANDLERS */
853: /* ------------------------------------------------------------------------- */
854:
855: PRIVATE void rdf_setHandlers (XML_Parser me)
856: {
857: XML_SetElementHandler(me, XML_startElement, XML_endElement);
858: XML_SetCharacterDataHandler(me, XML_characterData);
859: XML_SetProcessingInstructionHandler(me, XML_processingInstruction);
860: XML_SetDefaultHandler(me, XML_default);
861: XML_SetUnparsedEntityDeclHandler(me, XML_unparsedEntityDecl);
862: XML_SetNotationDeclHandler(me, XML_notationDecl);
863: XML_SetExternalEntityRefHandler(me, XML_externalEntityRef);
864: XML_SetUnknownEncodingHandler(me, XML_unknownEncoding, NULL);
865: }
866:
867: PRIVATE void rdf_newInstance (HTStream * me,
868: HTRequest * request,
869: HTFormat target_format,
870: HTStream * target_stream,
871: XML_Parser xmlparser,
872: void * context)
873: {
874: if (me && xmlparser) {
875: rdf_setHandlers(xmlparser);
876: XML_SetUserData(xmlparser, context);
877:
878: /* Call the new RDF instance callback (if any) with this new stream */
879: if (RDFInstance)
880: (*RDFInstance)(me, request, target_format, target_stream, context, RDFInstanceContext);
881: }
882: }
883:
884: /* ------------------------------------------------------------------------- */
885: /* RDF PARSER */
886: /* ------------------------------------------------------------------------- */
887:
888: PRIVATE void visit_element_children (HTList *children)
889: {
890: HTElement *child = NULL;
891: HTList *cur = children;
892: while ((child = (HTElement *) HTList_nextObject(cur))) {
893: if (!HTList_isEmpty(child->m_children))
894: visit_element_children(child->m_children);
895: HTElement_delete(child);
896: }
897: }
898:
899: PRIVATE void delete_elements (HTRDF * me)
900: {
901: if (me && me->m_root) {
902: HTElement *r = me->m_root;
903: if (!HTList_isEmpty(r->m_children))
904: visit_element_children(r->m_children);
905: HTElement_delete(r);
906: }
907: }
908:
909: PUBLIC HTRDF * HTRDF_new (void)
910: {
911: HTRDF * me;
912: if ((me = (HTRDF *) HT_CALLOC(1, sizeof(HTRDF))) == NULL)
913: HT_OUTOFMEM("HTRDF_new");
914: me->m_namespaceStack = HTList_new();
915: me->m_elementStack = HTList_new();
916:
917: me->m_triples = HTList_new();
918: me->m_vAllNameSpaces = HTList_new();
919:
920: me->m_bCreateBags = FALSE;
921: me->m_bFetchSchemas = FALSE;
922:
923: me->m_parseTypeStack = HTList_new();
924: me->m_parseElementStack = HTList_new();
925:
926: me->m_vResources = HTList_new();
927: me->m_vResolveQueue = HTList_new();
928: me->m_hIDtable = HTHashtable_new(0);
929:
930: return me;
931: }
932:
933: PUBLIC BOOL HTRDF_delete (HTRDF * me)
934: {
935: if (me) {
936: delete_elements(me);
937: if (me->m_namespaceStack) {
938: HTList *cur = me->m_namespaceStack;
939: HTAssocList *alist = NULL;
940: while ((alist = (HTAssocList *) HTList_nextObject(cur))) {
941: HTAssocList_delete(alist);
942: }
943: HTList_delete(me->m_namespaceStack);
944: }
945: if (me->m_elementStack) HTList_delete(me->m_elementStack);
946: me->m_root = NULL;
947: if (me->m_triples) {
948: HTList *cur = me->m_triples;
949: HTTriple *t = NULL;
950: while ((t = (HTTriple *) HTList_nextObject(cur))) {
951: /*HTTriple_print(t);*/
952: HTTriple_delete(t);
953: }
954: HTList_delete(me->m_triples);
955: }
956: HT_FREE(me->m_sSource);
957: if (me->m_vAllNameSpaces) {
958: HTList *cur = me->m_vAllNameSpaces;
2.3 frystyk 959: char * s = NULL;
960: while ((s = (char *) HTList_nextObject(cur))) {
2.1 frystyk 961: HT_FREE(s);
962: }
963: HTList_delete(me->m_vAllNameSpaces);
964: }
965: if (me->m_parseTypeStack)
966: HTList_delete(me->m_parseTypeStack);
967: if (me->m_parseElementStack)
968: HTList_delete(me->m_parseElementStack);
969: if (me->m_vResources)
970: HTList_delete(me->m_vResources);
971: if (me->m_vResolveQueue)
972: HTList_delete(me->m_vResolveQueue);
973: if (me->m_hIDtable)
974: HTHashtable_delete(me->m_hIDtable);
975: HT_FREE(me->m_sLiteral);
976: HT_FREE(me);
977: return YES;
978: }
979: return NO;
980: }
981:
982: /*
983: * setSource method saves the name of the source document for
984: * later inspection if needed
985: */
2.3 frystyk 986: PUBLIC BOOL HTRDF_setSource(HTRDF *me, char * source)
2.1 frystyk 987: {
988: if (me && source) {
989: StrAllocCopy (me->m_sSource, source);
990: return YES;
991: }
992: return NO;
993: }
994:
995: /*
996: * Go through the m_vResolveQueue and assign
997: * direct object reference for each symbolic reference
998: */
999: PUBLIC BOOL HTRDF_resolve (HTRDF * me)
1000: {
1001: if (me) {
1002: HTList * cur = me->m_vResolveQueue;
1003: HTElement *e = NULL;
1004: HTElement *e2 = NULL;
1005: while ((e = (HTElement *) HTList_nextObject(cur))) {
2.3 frystyk 1006: char * sAbout = HTElement_getAttribute2(e, RDFMS, "about");
1007: char * sResource = HTElement_getAttribute2(e, RDFMS, "resource");
1008: char * sAboutEach = HTElement_getAttribute2(e, RDFMS, "aboutEach");
1009: char * sAboutEachPrefix = HTElement_getAttribute2(e, RDFMS,
2.1 frystyk 1010: "aboutEachPrefix");
1011: if (sAbout) {
1012: if (sAbout[0]=='#')
1013: sAbout = &(sAbout[1]);
1014: e2 = (HTElement *) HTRDF_lookforNode(me, sAbout);
1015: if (e2)
1016: HTElement_addTarget(e, e2);
1017: else
1018: HTPrint("Unresolved internal reference %s\n", sAbout);
1019: }
1020: if (sResource) {
1021: if (sResource[0]=='#')
1022: sResource = &(sResource[1]);
1023: e2 = (HTElement *) HTRDF_lookforNode(me, sResource);
1024: if (e2)
1025: HTElement_addTarget(e, e2);
1026: }
1027:
1028: if (sAboutEach) {
1029: sAboutEach = &(sAboutEach[1]);
1030: e2 = (HTElement *) HTRDF_lookforNode(me, sAboutEach);
1031: if (e2)
1032: HTElement_addTarget(e, e2);
1033: }
1034: if (sAboutEachPrefix) {
1035: HTList * curr = me->m_vResources;
1036: HTElement *ele = NULL;
1037: while ((ele = (HTElement *) HTList_nextObject(curr))) {
2.3 frystyk 1038: char * sA = HTElement_getAttribute2(ele, RDFMS, "about");
2.1 frystyk 1039: if (sA &&
1040: !strncmp(sA, sAboutEachPrefix, strlen(sAboutEachPrefix))) {
1041: HTElement_addTarget(e, ele);
1042: }
1043: }
1044: }
1045: }
1046: HTList_delete(me->m_vResources);
1047: me->m_vResources = HTList_new();
1048: return YES;
1049: }
1050: return NO;
1051: }
1052:
1053: /**
1054: * Check if the element e is from the namespace
1055: * of the RDF schema by comparing only the beginning of
1056: * the expanded element name with the canonical RDFMS
1057: * URI
1058: */
1059: PUBLIC BOOL HTRDF_isRDF(HTRDF * me, HTElement *e)
1060: {
1061: return (me && e && e->m_sName) ?
1062: (!strncmp(e->m_sName, RDFMS, strlen(RDFMS))) : NO;
1063: }
1064:
1065: PUBLIC BOOL HTRDF_isRDFroot (HTRDF * me, HTElement *e)
1066: {
1067: if (me && e && e->m_sName) {
1068: int len = strlen(e->m_sName);
1069: if (len > 3) return (HTRDF_isRDF(me, e) && !strcmp(&(e->m_sName[len-3]), "RDF"));
1070: }
1071: return NO;
1072: }
1073:
1074: /**
1075: * Is the element a Description
1076: */
1077: PUBLIC BOOL HTRDF_isDescription (HTRDF *me, HTElement *e)
1078: {
1079: if (me && e && e->m_sName) {
1080: int len = strlen(e->m_sName);
1081: if (len > 11) return (HTRDF_isRDF(me, e) && !strcmp(&(e->m_sName[len-11]), "Description"));
1082: }
1083: return NO;
1084: }
1085:
1086: /*
1087: * Is the element a ListItem
1088: */
1089: PUBLIC BOOL HTRDF_isListItem (HTRDF *me, HTElement *e)
1090: {
1091: if (me && e && e->m_sName) {
1092: int len = strlen(e->m_sName);
1093: if (len > 2)
1094: return (HTRDF_isRDF(me, e) && (!strcmp(&(e->m_sName[len-2]), "li") || strchr(e->m_sName,'_')));
1095: }
1096: return NO;
1097: }
1098:
1099: /**
1100: * Is the element a Sequence
1101: */
1102: PUBLIC BOOL HTRDF_isSequence (HTRDF *me, HTElement *e)
1103: {
1104: if (me && e && e->m_sName) {
1105: int len = strlen(e->m_sName);
1106: if (len > 3) return (HTRDF_isRDF(me, e) && !strcmp(&(e->m_sName[len-3]), "Seq"));
1107: }
1108: return NO;
1109: }
1110:
1111: /*
1112: * Is the element an Alternative
1113: */
1114: PUBLIC BOOL HTRDF_isAlternative (HTRDF *me, HTElement *e)
1115: {
1116: if (me && e && e->m_sName) {
1117: int len = strlen(e->m_sName);
1118: if (len > 3) return (HTRDF_isRDF(me, e) && !strcmp(&(e->m_sName[len-3]), "Alt"));
1119: }
1120: return NO;
1121: }
1122:
1123: /*
1124: * Is the element a Bag
1125: */
1126: PUBLIC BOOL HTRDF_isBag (HTRDF *me, HTElement *e)
1127: {
1128: if (me && e && e->m_sName) {
1129: int len = strlen(e->m_sName);
1130: if (len > 3) return (HTRDF_isRDF(me, e) && !strcmp(&(e->m_sName[len-3]), "Bag"));
1131: }
1132: return NO;
1133: }
1134:
1135: /**
1136: * Is the element a Container
1137: */
1138: PUBLIC BOOL HTRDF_isContainer (HTRDF *me, HTElement *e)
1139: {
1140: return (HTRDF_isSequence(me, e) ||
1141: HTRDF_isAlternative(me, e) ||
1142: HTRDF_isBag(me, e));
1143: }
1144:
1145: /*
1146: * This method matches all properties but those from RDF namespace
1147: */
1148: PUBLIC BOOL HTRDF_isTypedPredicate(HTRDF *me, HTElement *e)
1149: {
1150: if (me && e && e->m_sName) {
1151: int len = strlen(e->m_sName);
2.3 frystyk 1152: char * tp[] = {"predicate", "subject", "object",
2.1 frystyk 1153: "value", "type", "Property", "Statement"};
1154: int i;
1155: if (HTRDF_isRDF(me, e)) {
1156: for(i = 0; i< 7; i++) {
1157: int ntp = strlen(tp[i]);
1158: if (len > ntp) {
1159: if (!strcmp(&(e->m_sName[len-ntp]), tp[i]))
1160: return YES;
1161: }
1162: }
1163: return NO;
1164: }
1165: if (len > 0) return YES;
1166: }
1167: return NO;
1168: }
1169:
2.3 frystyk 1170: PRIVATE void HTRDF_processListItem (HTRDF * me, char * sID, HTElement *listitem,
2.1 frystyk 1171: int iCounter)
1172: {
1173: /*
1174: * Two different cases for
1175: * 1. LI element without content (resource available)
1176: * 2. LI element with content (resource unavailable)
1177: */
2.3 frystyk 1178: char * cName = NULL;
1179: char * sResource = HTRDF_getResource(me, listitem);
2.1 frystyk 1180: char sdig[20];
1181: sprintf(sdig, "_%d", iCounter);
1182: StrAllocMCopy(&cName, RDFMS, sdig, NULL);
1183: if (sResource) {
1184: HTRDF_addTriple(me, cName, sID, sResource);
1185: /* validity checking */
1186: if (!HTList_isEmpty(listitem->m_children)){
1187: HTPrint("Listitem with resource attribute can not have child nodes");
1188: }
1189: StrAllocCopy(listitem->m_sID, sResource);
1190: } else {
1191: HTList *cur = listitem->m_children;
1192: HTElement *n = NULL;
1193: while ((n = (HTElement *) HTList_nextObject(cur))) {
1194: if (HTElement_instanceOfData(n)) {
1195: HTRDF_addTriple(me, cName, sID, n->m_sContent);
1196: } else if (HTRDF_isDescription(me, n)) {
2.3 frystyk 1197: char * sNodeID = HTRDF_processDescription(me, n, NO, YES, NO);
2.1 frystyk 1198: HTRDF_addTriple(me, cName, sID, sNodeID);
1199: StrAllocCopy(listitem->m_sID, sNodeID);
1200: } else if (HTRDF_isListItem(me, n)) {
1201: HTPrint("Can not nest list item inside list item\n");
1202: } else if (HTRDF_isContainer(me, n)) {
2.3 frystyk 1203: char * c = HTRDF_processContainer(me, n);
2.1 frystyk 1204: HTRDF_addTriple(me, cName, sID, n->m_sID);
1205: HT_FREE(c);
1206: } else if (HTRDF_isTypedPredicate(me, n)) {
2.3 frystyk 1207: char * sNodeID = HTRDF_processTypedNode(me, n);
2.1 frystyk 1208: HTRDF_addTriple(me, cName, sID, sNodeID);
1209: HT_FREE(sNodeID);
1210: }
1211: }
1212: }
1213: HT_FREE(cName);
1214: }
1215:
2.3 frystyk 1216: PRIVATE char * HTRDF_processContainer(HTRDF *me, HTElement *n)
2.1 frystyk 1217: {
2.3 frystyk 1218: char * sID = NULL;
1219: char * tName = NULL;
1220: char * aName = NULL;
1221: char * sName = NULL;
1222: char * bName = NULL;
2.1 frystyk 1223: StrAllocMCopy(&tName, RDFMS, "type", NULL);
1224: StrAllocMCopy(&aName, RDFMS, "Alt", NULL);
1225: StrAllocMCopy(&sName, RDFMS, "Seq", NULL);
1226: StrAllocMCopy(&bName, RDFMS, "Bag", NULL);
1227:
1228: StrAllocCopy(sID, n->m_sID);
1229: if (!sID)
1230: sID = HTRDF_newReificationID(me);
1231: /*
1232: * Do the instantiation only once
1233: */
1234: if (!n->m_bDone) {
1235: if (HTRDF_isSequence(me, n)) {
1236: HTRDF_addTriple(me, tName, sID, sName);
1237: } else if (HTRDF_isAlternative(me, n)) {
1238: HTRDF_addTriple(me, tName, sID, aName);
1239: } else if (HTRDF_isBag(me, n)) {
1240: HTRDF_addTriple(me, tName, sID, bName);
1241: }
1242: n->m_bDone = YES;
1243: }
1244: HTRDF_expandAttributes(me, n, n);
1245:
1246: {
1247: HTList *cur = n->m_children;
1248: HTElement *n2 = NULL;
1249: int iCounter = 1;
1250: if (HTList_isEmpty(cur) && HTRDF_isAlternative(me, n))
1251: HTPrint("An RDF:Alt container must have at least one list item\n");
1252: while ((n2 = (HTElement *) HTList_nextObject(cur))) {
1253: if (HTRDF_isListItem(me, n2)) {
1254: HTRDF_processListItem(me, sID, n2, iCounter);
1255: iCounter++;
1256: } else {
1257: HTPrint("Can not nest %s, inside container\n", n2->m_sName);
1258: }
1259: }
1260: } /* end of block */
1261:
1262: HT_FREE(tName); HT_FREE(sName); HT_FREE(aName); HT_FREE(bName);
1263:
1264: return sID;
1265: }
1266: /*
1267: * Manage the typedNode production in the RDF grammar.
1268: *
1269: */
2.3 frystyk 1270: PUBLIC char * HTRDF_processTypedNode(HTRDF *me, HTElement *typedNode)
2.1 frystyk 1271: {
2.3 frystyk 1272: char * sID = HTElement_getAttribute2(typedNode, RDFMS, "ID");
1273: char * sBagID = HTElement_getAttribute2(typedNode, RDFMS, "bagID");
1274: char * sAbout = HTElement_getAttribute2(typedNode, RDFMS, "about");
1275: char * sAboutEach = HTElement_getAttribute2(typedNode, RDFMS, "aboutEach");
1276: /*char * sAboutEachPrefix = HTElement_getAttribute2(typedNode, RDFMS,
2.1 frystyk 1277: "aboutEachPrefix");*/
2.3 frystyk 1278: char * resource = HTElement_getAttribute2(typedNode, RDFMS, "resource");
1279: char * iName = NULL;
1280: char * bName = NULL;
1281: char * tName = NULL;
2.1 frystyk 1282:
2.3 frystyk 1283: char * sObject = NULL;
2.1 frystyk 1284:
1285: StrAllocMCopy(&iName, RDFMS, "ID", NULL);
1286: StrAllocMCopy(&bName, RDFMS, "bagID", NULL);
1287: StrAllocMCopy(&tName, RDFMS, "type", NULL);
1288:
1289: if (resource)
1290: HTPrint("resource attribute not allowed for a typedNode %s\n",
1291: typedNode->m_sName);
1292:
1293: /*
1294: * We are going to manage this typedNode using the processDescription
1295: * routine later on. Before that, place all properties encoded as
1296: * attributes to separate child nodes.
1297: */
1298: {
1299: HTAssoc * assoc;
1300: HTAssocList *cur = typedNode->m_attributes;
2.3 frystyk 1301: char * sAttribute = NULL;
1302: char * tValue = NULL;
1303: char * sValue = NULL;
2.1 frystyk 1304: while((assoc= (HTAssoc *) HTList_nextObject(cur))) {
1305: sAttribute = HTAssoc_name(assoc);
1306: sValue = HTAssoc_value(assoc);
1307: tValue = trim(sValue);
1308: if (strncmp(sAttribute, RDFMS, strlen(RDFMS)) &&
1309: strncmp(sAttribute, XMLSCHEMA, strlen(XMLSCHEMA))) {
1310: if (strlen(tValue) > 0) {
1311: HTAssocList *newAL = HTAssocList_new();
1312: HTElement *newPredicate = HTElement_new(sAttribute, newAL);
1313: HTElement *d = NULL;
1314: HTElement_addAttribute(newPredicate, iName,
1315: sAbout ? sAbout : sID);
1316: HTElement_addAttribute(newPredicate, bName, sBagID);
1317: d = HTElement_new2(tValue);
1318: HTElement_addChild(newPredicate, d);
1319: HTElement_addChild(typedNode, newPredicate);
1320: HTElement_removeAttribute(typedNode, sAttribute);
1321: }
1322: }
1323: HT_FREE(tValue);
1324: } /* end of while */
1325: }/* end of block */
1326: {
1327: if (sAbout)
1328: StrAllocCopy(sObject, sAbout);
1329: else if (sID)
1330: StrAllocCopy(sObject, sID);
1331: else
1332: sObject = HTRDF_newReificationID(me);
1333: StrAllocCopy(typedNode->m_sID, sObject);
1334:
1335: /* special case: should the typedNode have aboutEach attribute,
1336: ** the type predicate should distribute to pointed
1337: ** collection also -> create a child node to the typedNode
1338: */
1339: if (sAboutEach && !HTList_isEmpty(typedNode->m_vTargets)) {
1340: HTAssocList *newAL = HTAssocList_new();
1341: HTElement *newPredicate = HTElement_new(tName, newAL);
1342: HTElement *d = HTElement_new2(typedNode->m_sName);
1343: HTElement_addChild(newPredicate, d);
1344: HTElement_addChild(typedNode, newPredicate);
1345: } else {
1346: HTRDF_addTriple(me, tName, sObject, typedNode->m_sName);
1347: }
1348: HTRDF_processDescription(me, typedNode, NO, NO, YES);
1349: }/* end of block */
1350:
1351: HT_FREE(iName); HT_FREE(bName); HT_FREE(tName);
1352:
1353: return sObject;
1354: }
1355:
1356: /*
1357: * Start processing an RDF/XML document instance from the
1358: * root element rdf.
1359: *
1360: */
1361: PUBLIC BOOL HTRDF_processRDF (HTRDF *me, HTElement *e)
1362: {
1363: if (me && e) {
1364: HTList *cur = e->m_children;
1365: HTElement *ele = NULL;
1366: if (HTList_isEmpty(e->m_children)) {
1367: HTPrint("Empty RDF Element\n");
1368: return NO;
1369: }
1370: while ((ele= (HTElement *) HTList_nextObject(cur))) {
1371: if (HTRDF_isDescription(me, ele)) {
1372: HTRDF_processDescription(me, ele, NO, me->m_bCreateBags,
1373: me->m_bCreateBags);
1374: } else if (HTRDF_isContainer(me, ele)) {
2.3 frystyk 1375: char * c = HTRDF_processContainer(me, ele);
2.1 frystyk 1376: HT_FREE(c);
1377: } else if (HTRDF_isTypedPredicate(me, ele)) {
2.3 frystyk 1378: char * t = HTRDF_processTypedNode(me, ele);
2.1 frystyk 1379: HT_FREE(t);
1380: }
1381: }
1382: return YES;
1383: }
1384: return NO;
1385: }
1386:
1387: /*
1388: * processPredicate handles all elements not defined as special
1389: * RDF elements.
1390: *
1391: * predicate The predicate element itself
1392: * description Context for the predicate
1393: * sTarget The target resource
1394: * reificate Should this predicate be reificated
1395: *
1396: * return the new ID which can be used to identify the predicate
1397: *
1398: */
2.3 frystyk 1399: PRIVATE char * HTRDF_processPredicate (HTRDF * me,
2.1 frystyk 1400: HTElement * predicate,
1401: HTElement * description,
2.3 frystyk 1402: char * sTarget,
2.1 frystyk 1403: BOOL reificate)
1404: {
2.3 frystyk 1405: char * sStatementID = HTElement_getAttribute2(predicate, RDFMS, "ID");
1406: char * nsStatementID = NULL;
1407: char * sBagID = HTElement_getAttribute2(predicate, RDFMS, "bagID");
1408: char * sResource = HTRDF_getResource(me, predicate);
2.1 frystyk 1409:
1410: /*
1411: ** If a predicate has other attributes than rdf:ID, rdf:bagID,
1412: ** or xmlns... -> generate new triples according to the spec.
1413: ** (See end of Section 6)
1414: */
1415: {
1416: HTElement * place_holder = NULL;
1417: HTAssocList * newAL = HTAssocList_new();
2.3 frystyk 1418: char * fName = NULL;
1419: char * aName = NULL;
2.1 frystyk 1420:
1421: StrAllocMCopy(&fName, RDFMS, "Description", NULL);
1422: place_holder = HTElement_new(fName, newAL);
1423: HT_FREE(fName);
1424:
1425: if (HTRDF_expandAttributes(me, place_holder, predicate)) {
1426:
1427: /* error checking */
1428: if (!HTList_isEmpty(predicate->m_children)) {
1429: HTPrint("%s must be an empty element since it uses propAttr grammar production", predicate->m_sName);
1430: HTElement_delete(place_holder);
1431: return NULL;
1432: }
1433: StrAllocMCopy(&aName, RDFMS, "about", NULL);
1434:
1435: /* determine the 'about' part for the new statements */
1436: if (sStatementID) {
1437: HTElement *data = HTElement_new2(sStatementID);
1438: HTElement_addAttribute(place_holder, aName, sStatementID);
1439:
1440: /* hack: make rdf:ID the value of the predicate */
1441: HTElement_addChild(predicate, data);
1442: } else if (sResource) {
1443: HTElement_addAttribute(place_holder, aName, sResource);
1444: } else {
1445: nsStatementID = HTRDF_newReificationID(me);
1446: HTElement_addAttribute(place_holder, aName, nsStatementID);
1447: HT_FREE(nsStatementID);
1448: }
1449: HT_FREE(aName);
1450:
1451: if (sBagID) {
1452: StrAllocMCopy(&fName, RDFMS, "bagID", NULL);
1453: HTElement_addAttribute(place_holder, fName, sBagID);
1454: HT_FREE(fName);
1455: StrAllocCopy(place_holder->m_sBagID, sBagID);
1456: }
1457: HTRDF_processDescription(me, place_holder, NO, NO, me->m_bCreateBags);
1458: } else {
1459:
1460: /* Nothing but xmlns or RDF stuff, so we don't need new element */
1461: HTElement_delete(place_holder);
1462: }
1463: }
1464:
1465: /*
1466: ** Tricky part: if the resource attribute is present for a predicate
1467: ** AND there are no children, the value of the predicate is either
1468: ** 1. the URI in the resource attribute OR
1469: ** 2. the node ID of the resolved #resource attribute
1470: */
1471: if (sResource && HTList_isEmpty(predicate->m_children)) {
1472: if (!HTElement_target(predicate)) {
1473: if (reificate) {
1474: HT_FREE(nsStatementID);
1475: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1476: sTarget, sResource,
1477: predicate->m_sID);
1478: StrAllocCopy(predicate->m_sID, nsStatementID);
1479: } else {
1480: HTRDF_addTriple(me, predicate->m_sName, sTarget, sResource);
1481: }
1482: } else {
1483: HTElement *target = HTElement_target(predicate);
1484: if (reificate) {
1485: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1486: sTarget,
1487: target->m_sID,
1488: predicate->m_sID);
1489: StrAllocCopy(predicate->m_sID, nsStatementID);
1490: } else {
1491: HTRDF_addTriple(me, predicate->m_sName, sTarget, target->m_sID);
1492: }
1493: }
1494: StrAllocCopy(nsStatementID, predicate->m_sID);
1495: return nsStatementID;
1496: }
1497:
1498: /*
1499: ** Does this predicate make a reference somewhere using the
1500: ** sResource attribute
1501: */
1502: if (sResource && HTElement_target(predicate)) {
2.3 frystyk 1503: char * dStatementID = HTRDF_processDescription(me,
2.1 frystyk 1504: HTElement_target(predicate),
1505: YES, NO, NO);
1506: if (reificate) {
1507: HT_FREE(nsStatementID);
1508: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1509: sTarget, dStatementID,
1510: predicate->m_sID);
1511: StrAllocCopy(predicate->m_sID, nsStatementID);
1512: } else {
1513: StrAllocCopy(nsStatementID, dStatementID);
1514: HTRDF_addTriple(me, predicate->m_sName, sTarget, nsStatementID);
1515: }
1516: return nsStatementID;
1517: }
1518:
1519: /*
1520: ** Before looping through the children, let's check
1521: ** if there are any. If not, the value of the predicate is
1522: ** an anonymous node
1523: */
1524: {
1525: HTList *cur = predicate->m_children;
1526: BOOL bUsedTypedNodeProduction = NO;
1527: HTElement *n2;
1528: StrAllocCopy(nsStatementID, sStatementID);
1529: if (HTList_isEmpty(cur)) {
1530: if (reificate) {
2.3 frystyk 1531: char * nr = HTRDF_newReificationID(me);
2.1 frystyk 1532: HT_FREE(nsStatementID);
1533: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1534: sTarget, nr,
1535: predicate->m_sID);
1536: HT_FREE(nr);
1537: } else {
2.3 frystyk 1538: char * nr = HTRDF_newReificationID(me);
2.1 frystyk 1539: HTRDF_addTriple(me, predicate->m_sName, sTarget, nr);
1540: HT_FREE(nr);
1541: }
1542: }
1543: while ((n2= (HTElement *) HTList_nextObject(cur))) {
1544: if (HTRDF_isDescription(me, n2)) {
1545: HTElement *d2 = n2;
2.3 frystyk 1546: char * dStatementID =HTRDF_processDescription(me, d2, YES, NO, NO);
2.1 frystyk 1547: StrAllocCopy(d2->m_sID, dStatementID);
1548:
1549: if (reificate) {
1550: HT_FREE(nsStatementID);
1551: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1552: sTarget, dStatementID,
1553: predicate->m_sID);
1554: } else {
1555: StrAllocCopy(nsStatementID, dStatementID);
1556: HTRDF_addTriple(me, predicate->m_sName, sTarget,
1557: nsStatementID);
1558: }
1559: } else if (HTElement_instanceOfData(n2)) {
2.3 frystyk 1560: char * tValue = NULL;
1561: char * sValue = n2->m_sContent;
2.1 frystyk 1562: /* we've got real data */
1563: /*
1564: * Only if the content is not empty PCDATA (whitespace that is)
1565: * print the triple
1566: */
1567: tValue = trim(sValue);
1568: if (tValue && strlen(tValue) > 0) {
1569: if (reificate) {
1570: HT_FREE(nsStatementID);
1571: nsStatementID = HTRDF_reificate (me, predicate->m_sName,
1572: sTarget, tValue,
1573: predicate->m_sID);
1574: StrAllocCopy(predicate->m_sID, nsStatementID);
1575: } else {
1576: HTRDF_addTriple(me, predicate->m_sName, sTarget, tValue);
1577: }
1578: }
1579: HT_FREE(tValue);
1580: } else if (HTRDF_isContainer(me, n2)) {
1581: HTElement *target = HTElement_target(description);
2.3 frystyk 1582: char * aboutTarget =
2.1 frystyk 1583: target ?
1584: HTElement_getAttribute2(target, RDFMS, "about") : NULL;
2.3 frystyk 1585: char * sCollectionID = HTRDF_processContainer(me, n2);
2.1 frystyk 1586: StrAllocCopy(nsStatementID, sCollectionID);
1587: /* Attach the collection to the current predicate */
1588: if (target) {
1589: if (reificate) {
1590: HT_FREE(nsStatementID);
1591: nsStatementID=HTRDF_reificate (me, predicate->m_sName,
1592: aboutTarget,
1593: sCollectionID,
1594: predicate->m_sID);
1595: StrAllocCopy(predicate->m_sID, nsStatementID);
1596: } else {
1597: HTRDF_addTriple(me, predicate->m_sName, aboutTarget,
1598: sCollectionID);
1599: }
1600: } else {
1601: if (reificate) {
1602: HT_FREE(nsStatementID);
1603: nsStatementID=HTRDF_reificate (me, predicate->m_sName,
1604: sTarget, sCollectionID,
1605: predicate->m_sID);
1606: StrAllocCopy(predicate->m_sID, nsStatementID);
1607: } else {
1608: HTRDF_addTriple(me, predicate->m_sName, sTarget,
1609: sCollectionID);
1610: }
1611: }
1612: HT_FREE(sCollectionID);
1613: } else if (HTRDF_isTypedPredicate(me, n2)) {
1614: if (bUsedTypedNodeProduction) {
1615: HTPrint("Only one typedNode allowed inside a predicate (Extra typedNode: %s )\n", n2->m_sName);
1616: } else {
1617: bUsedTypedNodeProduction = YES;
1618: }
1619: HT_FREE(nsStatementID);
1620: nsStatementID = HTRDF_processTypedNode(me, n2);
1621: HTRDF_addTriple(me, predicate->m_sName, sTarget, nsStatementID);
1622: }
1623: }
1624: return nsStatementID;
1625: } /* end of block */
1626: return NULL;
1627: }
1628:
1629: /*
1630: * processDescription manages Description elements
1631: *
1632: * description The Description element itself
1633: * inPredicate Is this is a nested description
1634: * reificate Do we need to reificate
1635: * createBag Do we create a bag container
1636: *
1637: * return An ID for the description
1638: *
1639: */
2.3 frystyk 1640: PUBLIC char * HTRDF_processDescription (HTRDF * me,
2.1 frystyk 1641: HTElement * description,
1642: BOOL inPredicate,
1643: BOOL reificate,
1644: BOOL createBag)
1645: {
1646: int iChildCount = 1;
1647: BOOL bOnce = YES;
1648:
2.3 frystyk 1649: char * sAbout = HTElement_getAttribute2(description, RDFMS, "about");
1650: char * sAboutEach = HTElement_getAttribute2(description, RDFMS, "aboutEach");
1651: char * sAboutEachPrefix = HTElement_getAttribute2(description, RDFMS,
2.1 frystyk 1652: "aboutEachPrefix");
2.3 frystyk 1653: char * sBagid = HTElement_getAttribute2(description, RDFMS, "bagID");
1654: char * sID = HTElement_getAttribute2(description, RDFMS, "ID");
2.1 frystyk 1655: HTElement *target = HTElement_target(description);
1656: BOOL hasTarget = HTList_isEmpty(description->m_vTargets) ? NO : YES;
1657: BOOL targetIsContainer = NO;
2.3 frystyk 1658: char * sTargetAbout = NULL;
1659: char * sTargetBagID = NULL;
1660: char * sTargetID = NULL;
1661: char * dName = NULL;
1662: char * aName = NULL;
2.1 frystyk 1663:
1664: /*
1665: ** Return immediately if the description has already been managed
1666: */
1667: if (description->m_bDone) return description->m_sID;
1668:
1669: StrAllocMCopy(&dName, RDFMS, "Description", NULL);
1670: StrAllocMCopy(&aName, RDFMS, "about", NULL);
1671:
1672: /*
1673: ** Determine what the target of the Description reference is
1674: */
1675: if (hasTarget) {
2.3 frystyk 1676: char * sTargetID2 = HTElement_getAttribute2(target, RDFMS, "ID");
2.1 frystyk 1677: sTargetAbout = HTElement_getAttribute2(target, RDFMS, "about");
1678: sTargetBagID = HTElement_getAttribute2(target, RDFMS, "bagID");
1679: if (me->m_sSource && sTargetID2) {
1680: StrAllocMCopy(&sTargetID, me->m_sSource, sTargetID2, NULL);
1681: } else {
1682: StrAllocCopy(sTargetID, sTargetID2);
1683: }
1684: /*
1685: * Target is collection if
1686: * 1. it is identified with bagID attribute
1687: * 2. it is identified with ID attribute and is a collection
1688: */
1689: if (sTargetBagID && sAbout) {
1690: targetIsContainer = !strcmp(&(sAbout[1]), sTargetBagID);
1691: } else {
1692: if (sTargetID && sAbout && !strcmp(&(sAbout[1]), sTargetID) &&
1693: HTRDF_isContainer(me, target))
1694: targetIsContainer = YES;
1695: }
1696: HT_FREE(sTargetID);
1697: }
1698:
1699: /*
1700: * Check if there are properties encoded using the abbreviated
1701: * syntax
1702: */
1703: HTRDF_expandAttributes(me, description, description);
1704:
1705: /*
1706: * Manage the aboutEach attribute here
1707: */
1708: if (sAboutEach && hasTarget) {
1709: if (HTRDF_isContainer(me, target)) {
1710: HTList *cur = target->m_children;
1711: HTElement *ele = NULL;
1712: while ((ele= (HTElement *) HTList_nextObject(cur))) {
1713: if (HTRDF_isListItem(me, ele)) {
2.3 frystyk 1714: char * sResource = HTRDF_getResource(me, ele);
2.1 frystyk 1715: if (sResource) {
1716: HTElement * newDescription = NULL;
1717: HTElement * ele2;
1718: HTList * cur2 = description->m_children;
1719:
1720: /*
1721: * Manage <li resource="..." /> case
1722: */
1723: if (sResource) {
1724: HTAssocList *newAL = HTAssocList_new();
1725: newDescription = HTElement_new(dName, newAL);
1726: HTElement_addAttribute(newDescription, aName, sResource);
1727: }
1728:
1729: while ((ele2 = (HTElement *) HTList_nextObject(cur2))){
1730: if (newDescription) HTElement_addChild(newDescription, ele2);
1731: }
1732:
1733: if (newDescription)
1734: HTRDF_processDescription(me, newDescription, NO, NO, NO);
1735:
1736: /* Not needed anymore */
1737: HTElement_delete(newDescription);
1738:
1739: } else {
1740: /**
1741: * Otherwise we have a structured value inside <li>
1742: *
1743: * loop through the children of <li>
1744: * (can be only one)
1745: */
1746: HTList *cur2 = ele->m_children;
1747: HTElement *ele2 = NULL;
1748: while ((ele2 = (HTElement *) HTList_nextObject(cur2))) {
1749: HTAssocList *newAL = HTAssocList_new();
1750: HTElement *newNode = HTElement_new(dName, newAL);
1751: HTList *cur3 = description->m_children;
1752: HTElement *ele3 = NULL;
1753: /* loop through the items in the
1754: * description with aboutEach
1755: * and add them to the target
1756: */
1757: while ((ele3 = (HTElement *)
1758: HTList_nextObject(cur3))) {
1759: HTElement_addChild(newNode, ele3);
1760: }
1761: HTElement_addTarget(newNode, ele2);
1762: HTRDF_processDescription(me, newNode, YES, NO, NO);
1763: }
1764: }
1765: } else if (HTRDF_isTypedPredicate(me, ele)) {
1766: HTAssocList *newAL = HTAssocList_new();
1767: HTElement *newNode = HTElement_new(dName, newAL);
1768: HTList *cur2 = description->m_children;
1769: HTElement *ele2 = NULL;
1770: while ((ele2 = (HTElement *) HTList_nextObject(cur2))) {
1771: HTElement_addChild(newNode, ele2);
1772: }
1773: HTElement_addTarget(newNode, ele);
1774: HTRDF_processDescription(me, newNode, YES, NO, NO);
1775: }
1776: } /* end of while */
1777: } else if (HTRDF_isDescription(me, target)) {
1778: HTList *cur = target->m_children;
1779: HTElement *ele = NULL;
1780: while ((ele = (HTElement *) HTList_nextObject(cur))) {
1781: HTAssocList *newAL = HTAssocList_new();
1782: HTElement *newNode = HTElement_new(dName, newAL);
1783: HTList *cur2 = description->m_children;
1784: HTElement *ele2 = NULL;
1785: while ((ele2 = (HTElement *) HTList_nextObject(cur2))) {
1786: HTElement_addChild(newNode, ele2);
1787: }
1788: HTElement_addTarget(newNode, ele);
1789: HTRDF_processDescription(me, newNode, YES, NO, NO);
1790: } /* end of while */
1791: }
1792:
1793: HT_FREE(dName);
1794: HT_FREE(aName);
1795: return NULL;
1796: }
1797:
1798: /*
1799: * Manage the aboutEachPrefix attribute here
1800: */
1801: if (sAboutEachPrefix) {
1802: if (hasTarget) {
1803: HTList *cur = description->m_vTargets;
1804: HTElement *target = NULL;
1805: while ((target = (HTElement *) HTList_nextObject(cur))) {
1806: HTList *cur2 = description->m_children;
1807: HTElement *ele2 = NULL;
1808: HTElement *newDescription = NULL;
1809: HTAssocList *newAL = HTAssocList_new();
1810: sTargetAbout = HTElement_getAttribute2(target, RDFMS, "about");
1811: newDescription = HTElement_new(dName, newAL);
1812: HTElement_addAttribute(newDescription, aName, sTargetAbout);
1813: while ((ele2 = (HTElement *) HTList_nextObject(cur2))) {
1814: HTElement_addChild(newDescription, ele2);
1815: }
1816: HTRDF_processDescription(me, newDescription, NO, NO, NO);
1817: }
1818: }
1819:
1820: HT_FREE(dName);
1821: HT_FREE(aName);
1822: return NULL;
1823: }
1824: /*
1825: * Enumerate through the children
1826: */
1827: {
1828: HTList *cur = description->m_children;
1829: HTElement *n = NULL;
1830: while ((n = (HTElement *) HTList_nextObject(cur))) {
1831: if (HTRDF_isDescription(me, n))
1832: HTPrint("Can not nest Description inside Description\n");
1833: else if (HTRDF_isListItem(me, n))
1834: HTPrint("Can not nest List Item inside Description\n");
1835: else if (HTRDF_isContainer(me, n))
1836: HTPrint("Can not nest Container inside Description\n");
1837: else if (HTRDF_isTypedPredicate(me, n)) {
2.3 frystyk 1838: char * sChildID = NULL;
2.1 frystyk 1839: if (hasTarget && targetIsContainer) {
1840: sChildID = HTRDF_processPredicate(me, n, description,
1841: target->m_sBagID ?
1842: target->m_sBagID :
1843: target->m_sID, NO);
1844: StrAllocCopy(description->m_sID, sChildID);
1845: createBag = NO;
1846: } else if (hasTarget) {
1847: sChildID = HTRDF_processPredicate(me, n, description,
1848: target->m_sBagID ?
1849: target->m_sBagID :
1850: target->m_sID, reificate);
1851: StrAllocCopy(description->m_sID, sChildID);
1852: } else if (!hasTarget && !inPredicate) {
1853: if (!description->m_sID) {
2.3 frystyk 1854: char * nr = HTRDF_newReificationID(me);
2.1 frystyk 1855: StrAllocCopy(description->m_sID, nr);
1856: HT_FREE(nr);
1857: }
1858: if (!sAbout) {
1859: if (sID)
1860: sAbout = sID;
1861: else
1862: sAbout = description->m_sID;
1863: }
1864: sChildID = HTRDF_processPredicate(me, n, description,
1865: sAbout, sBagid ?
1866: YES : reificate);
1867:
1868: } else if (!hasTarget && inPredicate) {
1869: if (!sAbout) {
1870: if (sID) {
1871: StrAllocCopy(description->m_sID, sID);
1872: sAbout = sID;
1873: } else {
1874: if (!description->m_sID) {
2.3 frystyk 1875: char * nr = HTRDF_newReificationID(me);
2.1 frystyk 1876: StrAllocCopy(description->m_sID, nr);
1877: HT_FREE(nr);
1878: }
1879: sAbout = description->m_sID;
1880: }
1881: } else {
1882: StrAllocCopy(description->m_sID, sAbout);
1883: }
1884: sChildID = HTRDF_processPredicate(me, n, description, sAbout, NO);
1885: }
1886: /*
1887: * Each Description block creates also a Bag node which
1888: * has links to all properties within the block IF
1889: * the m_bCreateBags variable is true
1890: */
1891: if (sBagid || (me->m_bCreateBags && createBag)) {
2.3 frystyk 1892: char * sNamespace = RDFMS;
2.1 frystyk 1893: if (bOnce && sChildID) {
2.3 frystyk 1894: char * tName = NULL;
1895: char * bName = NULL;
2.1 frystyk 1896: bOnce = NO;
1897: if (!description->m_sBagID) {
2.3 frystyk 1898: char * nr = HTRDF_newReificationID(me);
2.1 frystyk 1899: StrAllocCopy(description->m_sBagID, nr);
1900: HT_FREE(nr);
1901: }
1902: if (!description->m_sID)
1903: StrAllocCopy(description->m_sID,
1904: description->m_sBagID);
1905: StrAllocMCopy(&tName, sNamespace, "type", NULL);
1906: StrAllocMCopy(&bName, sNamespace, "Bag", NULL);
1907: HTRDF_addTriple(me, tName, description->m_sBagID, bName);
1908: HT_FREE(tName);
1909: HT_FREE(bName);
1910:
1911: }
1912: if (sChildID) {
2.3 frystyk 1913: char * tName = NULL;
2.1 frystyk 1914: char si[20];
1915: sprintf(si, "%d", iChildCount);
1916: StrAllocMCopy(&tName, sNamespace, "_", si, NULL);
1917: HTRDF_addTriple(me, tName, description->m_sBagID, sChildID);
1918: iChildCount++;
1919: HT_FREE(tName);
1920: }
1921: }
1922: HT_FREE(sChildID);
1923: }
1924: }
1925: } /* end of block*/
1926:
1927: description->m_bDone = YES;
1928:
1929: HT_FREE(dName);
1930: HT_FREE(aName);
1931: return (description->m_sID);
1932: }
1933:
1934: /*
1935: * Given an XML document (well-formed HTML, for example),
1936: * look for a suitable element to start parsing from
1937: *
1938: */
1939: PUBLIC BOOL HTRDF_processXML (HTRDF *me, HTElement *ele)
1940: {
1941: if (me && ele) {
1942: if (HTRDF_isRDF(me, ele)) {
1943: if (HTRDF_isRDFroot(me, ele)) {
1944: HTRDF_processRDF(me, ele);
1945: } else if (HTRDF_isDescription(me, ele)) {
1946: HTRDF_processDescription(me, ele, NO, me->m_bCreateBags,
1947: me->m_bCreateBags);
1948: }
1949: } else {
1950: HTList *cur = ele->m_children;
1951: HTElement *child = NULL;
1952: while ((child = (HTElement *) HTList_nextObject(cur))) {
1953: HTRDF_processXML(me, child);
1954: }
1955: }
1956:
1957: /* MISSING RECURSION */
1958:
1959: return YES;
1960: }
1961: return NO;
1962: }
1963:
1964: /*
1965: * Return the root element pointer. This requires the parsing
1966: * has been already done.
1967: */
1968: PUBLIC HTElement * HTRDF_root (HTRDF *me)
1969: {
1970: return me ? me->m_root : NULL;
1971: }
1972:
1973: /*
1974: * Return the full namespace URI for a given prefix sPrefix.
1975: * The default namespace is identified with xmlns prefix.
1976: * The namespace of xmlns attribute is an empty string.
1977: */
1978:
2.3 frystyk 1979: PUBLIC char * HTRDF_namespace(HTRDF * me, char * sPrefix)
2.1 frystyk 1980: {
2.3 frystyk 1981: char * nPrefix = NULL;
2.1 frystyk 1982: HTAssocList * calist;
1983: HTList * cur = me->m_namespaceStack;
1984:
1985: if (!sPrefix)
1986: StrAllocCopy(nPrefix, "xmlns");
1987:
1988: while ((calist = (HTAssocList *) HTList_nextObject(cur))) {
2.3 frystyk 1989: char * sValue = HTAssocList_findObjectCaseSensitiveExact(calist, sPrefix);
2.1 frystyk 1990: if (sValue) {
1991: StrAllocCopy(nPrefix, sValue);
1992: return nPrefix;
1993: }
1994: }
1995: /*
1996: * Give error only if
1997: * 1. the prefix is not from the reserved xml namespace
1998: * 2. the prefix is not xmlns which is to look for the default
1999: * namespace
2000: */
2001: if (!strcmp(sPrefix, XMLSCHEMA)) {
2002: StrAllocCopy(nPrefix, sPrefix);
2003: return nPrefix;
2004: } else if (!strcmp(sPrefix, "xmlns")) {
2005: StrAllocCopy(nPrefix, "");
2006: return nPrefix;
2007: } else
2008: HTPrint("Unresolved Namespace prefix %s\n", sPrefix);
2009:
2010: StrAllocCopy(nPrefix, "");
2011: return nPrefix;
2012: }
2013:
2014: /*
2015: * Methods to determine whether we are parsing
2016: * parseType="Literal" or parseType="Resource"
2017: */
2018:
2019: PUBLIC BOOL HTRDF_parseLiteral(HTRDF *me)
2020: {
2021: HTElement *e = NULL;
2022: HTList *cur = me->m_elementStack;
2023: if (!HTList_isEmpty(me->m_elementStack)) {
2024: while((e = (HTElement *) HTList_nextObject(cur))) {
2.3 frystyk 2025: char * sParseType = NULL;
2.1 frystyk 2026: sParseType = HTElement_getAttribute2(e, RDFMS, "parseType");
2027: if (sParseType) {
2028: if (strcmp(sParseType, "Resource"))
2029: return YES;
2030: }
2031: }
2032: }
2033: return NO;
2034: }
2035:
2036: /*
2037: * Methods to determine whether we are parsing
2038: * parseType="Literal" or parseType="Resource"
2039: */
2040:
2041: PUBLIC BOOL HTRDF_parseResource(HTRDF *me)
2042: {
2043: HTElement *e = NULL;
2044: HTList *cur = me->m_elementStack;
2045: if (!HTList_isEmpty(me->m_elementStack)) {
2046: while((e = (HTElement *) HTList_nextObject(cur))) {
2.3 frystyk 2047: char * sParseType = NULL;
2.1 frystyk 2048: sParseType = HTElement_getAttribute2(e, RDFMS, "parseType");
2049: if (sParseType) {
2050: if (!strcmp(sParseType, "Resource"))
2051: return YES;
2052: }
2053: }
2054: }
2055: return NO;
2056: }
2057: /*
2058: * checkAttributes goes through the attributes of element e<
2059: * to see
2060: * 1. if there are symbolic references to other nodes in the data model.
2061: * in which case they must be stored for later resolving with
2062: * resolveLater method.
2063: * 2. if there is an identity attribute, it is registered using
2064: * registerResource or registerID method.
2065: *
2066: */
2067:
2068: PRIVATE void HTRDF_checkAttributes(HTRDF *me, HTElement *e)
2069: {
2070: {
2.3 frystyk 2071: char * sResource = HTElement_getAttribute2(e, RDFMS, "resource");
2.1 frystyk 2072:
2073: if (sResource && sResource[0] == '#')
2074: HTRDF_resolveLater(me, e);
2075: }
2076: {
2.3 frystyk 2077: char * sAboutEach = HTElement_getAttribute2(e, RDFMS, "aboutEach");
2.1 frystyk 2078:
2079: if (sAboutEach && sAboutEach[0] == '#')
2080: HTRDF_resolveLater(me, e);
2081: }
2082: {
2.3 frystyk 2083: char * sAboutEachPrefix = HTElement_getAttribute2(e, RDFMS,
2.1 frystyk 2084: "aboutEachPrefix");
2085:
2086: if (sAboutEachPrefix && sAboutEachPrefix[0] == '#')
2087: HTRDF_resolveLater(me, e);
2088: }
2089: {
2.3 frystyk 2090: char * sAbout = HTElement_getAttribute2(e, RDFMS, "about");
2.1 frystyk 2091: if (sAbout) {
2092: if (sAbout[0] == '#')
2093: HTRDF_resolveLater(me, e);
2094: else
2095: HTRDF_registerResource(me, e);
2096: }
2097: }
2098:
2099: {
2.3 frystyk 2100: char * sBagID = HTElement_getAttribute2(e, RDFMS, "bagID");
2.1 frystyk 2101:
2102: if (sBagID) {
2103: HTRDF_registerID(me, sBagID, e);
2104: StrAllocCopy(e->m_sBagID, sBagID);
2105: }
2106: }
2107: {
2.3 frystyk 2108: char * sID = HTElement_getAttribute2(e, RDFMS, "ID");
2.1 frystyk 2109: if (sID) {
2110: HTRDF_registerID(me, sID, e);
2111: StrAllocCopy(e->m_sID, sID);
2112: }
2113: }
2114: }
2115: /*
2116: * Add the element e to the m_vResolveQueue
2117: * to be resolved later.
2118: */
2119: PUBLIC void HTRDF_resolveLater(HTRDF *me, HTElement *e)
2120: {
2121: HTList_addObject(me->m_vResolveQueue, e);
2122: }
2123: /*
2124: * Add an element e to the Hashtable m_hIDtable
2125: * which stores all nodes with an ID
2126: */
2127:
2.3 frystyk 2128: PUBLIC void HTRDF_registerID(HTRDF *me, char * sID, HTElement *e)
2.1 frystyk 2129: {
2130: if (HTHashtable_object(me->m_hIDtable, sID))
2131: HTPrint("Node ID %s redefined", sID);
2132: HTHashtable_addObject(me->m_hIDtable, sID, e);
2133: }
2134: /*
2135: * Add an element e to the Vector m_vResources
2136: * which stores all nodes with an URI
2137: */
2138: PUBLIC void HTRDF_registerResource(HTRDF *me, HTElement *e)
2139: {
2140: HTList_addObject(me->m_vResources, e);
2141: }
2142:
2143: /*
2144: * Look for a node by name sID from the Hashtable
2145: * m_hIDtable of all registered IDs.
2146: */
2147:
2.3 frystyk 2148: PUBLIC HTElement *HTRDF_lookforNode(HTRDF *me, char * sID)
2.1 frystyk 2149: {
2150: if (sID)
2151: return (HTElement *) HTHashtable_object(me->m_hIDtable, sID);
2152: return NULL;
2153: }
2154:
2155: /*
2156: ** Special method to deal with rdf:resource attribute
2157: */
2.3 frystyk 2158: PUBLIC char * HTRDF_getResource(HTRDF *me, HTElement *e)
2.1 frystyk 2159: {
2.3 frystyk 2160: char * sResource = HTElement_getAttribute2(e, RDFMS, "resource");
2.1 frystyk 2161: if (sResource != NULL && sResource[0] == '\0')
2162: sResource = me->m_sSource;
2163: return sResource;
2164: }
2165:
2166: /*
2167: ** Take an element ele with its parent element parent
2168: ** and evaluate all its attributes to see if they are non-RDF specific
2169: ** and non-XML specific in which case they must become children of
2170: ** the ele node.
2171: */
2172: PRIVATE BOOL HTRDF_expandAttributes (HTRDF * me, HTElement * parent, HTElement * ele)
2173: {
2174: BOOL foundAbbreviation = NO;
2.3 frystyk 2175: char * sAttribute = NULL;
2176: char * sValue = NULL;
2.1 frystyk 2177: HTAssoc * assoc;
2178: HTAssocList * cur = ele->m_attributes;
2179: int lxmlschema = strlen(XMLSCHEMA);
2180: int lrdfms = strlen(RDFMS);
2181:
2182: while ((assoc= (HTAssoc *) HTList_nextObject(cur))) {
2183: int latt;
2184: sAttribute = HTAssoc_name(assoc);
2185: sValue = HTAssoc_value(assoc);
2.4 ! barstow 2186:
2.1 frystyk 2187: latt = strlen(sAttribute);
2188: if (!strncmp(sAttribute, XMLSCHEMA, lxmlschema))
2189: continue;
2190:
2191: if (!strncmp(sAttribute, RDFMS, lrdfms) &&
2192: (sAttribute[lrdfms]!='_') &&
2193: latt > 5 && strcmp(&(sAttribute[latt-5]), "value") &&
2194: strcmp(&(sAttribute[latt-4]), "type"))
2195: continue;
2196:
2197: if (strlen(sValue) > 0) {
2198: HTAssocList * newAL = HTAssocList_new();
2199: HTElement * newElement = HTElement_new(sAttribute, newAL);
2200: HTElement * newData = HTElement_new2(sValue);
2201: HTElement_addChild(newElement, newData);
2202: HTElement_addChild(parent, newElement);
2203: foundAbbreviation = YES;
2204: }
2205: }
2206: return foundAbbreviation;
2207: }
2208:
2209: /**
2210: * Create a new reification ID by using a name part and an
2211: * incremental counter m_iReificationCounter.
2212: */
2.3 frystyk 2213: PUBLIC char * HTRDF_newReificationID (HTRDF *me)
2.1 frystyk 2214: {
2.3 frystyk 2215: char * nsid = NULL;
2.1 frystyk 2216: char nsrc[20];
2217: me->m_iReificationCounter++;
2218: sprintf(nsrc, "%d", me->m_iReificationCounter);
2219: if (!me->m_sSource) {
2220: StrAllocMCopy(&nsid, "genid", nsrc, NULL);
2221: } else {
2222: StrAllocMCopy(&nsid, me->m_sSource, "#genid", nsrc, NULL);
2223: }
2224: return nsid;
2225: }
2226:
2227: /*
2228: * reificate creates one new node and four new triples
2229: * and returns the ID of the new node
2230: */
2231:
2.3 frystyk 2232: PRIVATE char * HTRDF_reificate(HTRDF *me, char * sPredicate, char * sSubject,
2233: char * sObject, char * sNodeID)
2.1 frystyk 2234: {
2.3 frystyk 2235: char * sName = NULL;
2236: char * pName = NULL;
2237: char * oName = NULL;
2238: char * tName = NULL;
2239: char * stName = NULL;
2240: char * tNodeID = NULL;
2.1 frystyk 2241:
2242: if (!sNodeID)
2243: tNodeID = HTRDF_newReificationID(me);
2244: else
2245: StrAllocCopy(tNodeID, sNodeID);
2246:
2247: StrAllocMCopy(&sName, RDFMS, "subject", NULL);
2248: StrAllocMCopy(&pName, RDFMS, "predicate", NULL);
2249: StrAllocMCopy(&oName, RDFMS, "object", NULL);
2250: StrAllocMCopy(&tName, RDFMS, "type", NULL);
2251: StrAllocMCopy(&stName, RDFMS, "Statement", NULL);
2252:
2253: /*
2254: * The original statement must remain in the data model
2255: */
2256: HTRDF_addTriple(me, sPredicate, sSubject, sObject);
2257:
2258: /*
2259: * Do not reificate reificated properties
2260: */
2261: if (strcmp(sPredicate, sName) && strcmp(sPredicate, pName) &&
2262: strcmp(sPredicate, oName) && strcmp(sPredicate, tName)) {
2263:
2264: /* Reificate by creating 4 new triples */
2265: HTRDF_addTriple(me, pName, tNodeID, sPredicate);
2266: HTRDF_addTriple(me, sName, tNodeID, (sSubject[0]=='\0' ? me->m_sSource: sSubject));
2267: HTRDF_addTriple(me, oName, tNodeID, sObject);
2268: HTRDF_addTriple(me, tName, tNodeID, stName);
2269: } else
2270: HT_FREE(tNodeID);
2271:
2272: HT_FREE(sName);
2273: HT_FREE(pName);
2274: HT_FREE(oName);
2275: HT_FREE(tName);
2276: HT_FREE(stName);
2277:
2278: return tNodeID;
2279: }
2280: /*
2281: * Create a new triple and add it to the m_triples List
2282: * Send the triple to the Output stream
2283: */
2284:
2.3 frystyk 2285: PUBLIC void HTRDF_addTriple (HTRDF *me, char * sPredicate, char * sSubject,
2286: char * sObject)
2.1 frystyk 2287: {
2288: HTTriple *t = NULL;
2289:
2290: /*
2291: * If there is no subject (about=""), then use the URI/filename where
2292: * the RDF description came from
2293: */
2294: if (!sPredicate || !sSubject || !sObject) {
2295: HTPrint("Predicate %s when subject %s and object %s \n",
2296: sPredicate ? sPredicate : "null",
2297: sSubject ? sSubject : "null",
2298: sObject ? sObject : "null");
2299: return;
2300: }
2301:
2302: if (sSubject[0]=='\0')
2303: sSubject = me->m_sSource;
2304:
2305: t = HTTriple_new(sPredicate, sSubject, sObject);
2306:
2307: /* Call the triple callback handler (if any) with this new triple */
2308: if (me->newTripleInstance && t) (*(me->newTripleInstance))(me, t, me->tripleContext);
2309:
2310: HTList_addObject(me->m_triples, t);
2311: }
2312:
2313: /*
2314: * createBags method allows one to determine whether SiRPAC
2315: * produces Bag instances for each Description block.
2316: * The default setting is not to generate them.
2317: */
2318:
2319: PUBLIC void HTRDF_createBags(HTRDF *me, BOOL b)
2320: {
2321: if (me)
2322: me->m_bCreateBags = b;
2323: }
2324:
2325: /*
2326: Set output stream for RDF parser
2327: */
2328:
2329: PUBLIC void HTRDF_setOutputStream(HTRDF *me, HTStream *ostream)
2330: {
2331: if (me)
2332: me->ostream = ostream;
2333: }
2334:
2335: PUBLIC BOOL HTRDF_registerNewTripleCallback (HTRDF * me, HTTripleCallback_new * cbf, void * context)
2336: {
2337: if (me) {
2338: me->newTripleInstance = cbf;
2339: me->tripleContext = context;
2340: return YES;
2341: }
2342: return NO;
2343: }
2344:
2345: PUBLIC BOOL HTRDF_registerNewParserCallback (HTRDFCallback_new * me, void * context)
2346: {
2347: RDFInstance = me;
2348: RDFInstanceContext = context;
2349: return YES;
2350: }
2351:
2352: /* ------------------------------------------------------------------------- */
2353: /* HTRDFTriples STREAM HANDLERS */
2354: /* ------------------------------------------------------------------------- */
2355:
2356: PRIVATE int generate_triples(HTStream *me)
2357: {
2358: HTRDF *rdfp = me ? me->rdfparser : NULL;
2359: if (rdfp) {
2360:
2361: HTRDF_resolve(rdfp);
2362:
2363: HTRDF_processXML(rdfp, HTRDF_root(rdfp));
2364:
2365: return HT_OK;
2366: }
2367: return HT_ERROR;
2368: }
2369:
2370: PRIVATE int HTRDFTriples_flush (HTStream * me)
2371: {
2372: if (me->target)
2373: return (*me->target->isa->flush)(me->target);
2374: return HT_OK;
2375: }
2376:
2377: PRIVATE int HTRDFTriples_free (HTStream * me)
2378: {
2379: int status = HT_OK;
2380:
2381: status = generate_triples(me);
2382:
2383: HTRDF_delete(me->rdfparser);
2384:
2385: if (me->target) {
2386: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
2387: return HT_WOULD_BLOCK;
2388: }
2389: HTTRACE(XML_TRACE, "RDF Parser.. FREEING...\n");
2390: HT_FREE(me);
2391: return status;
2392: }
2393:
2394: PRIVATE int HTRDFTriples_abort (HTStream * me, HTList * e)
2395: {
2396: HTTRACE(XML_TRACE, "RDF Parser.. ABORTING...\n");
2397: HTRDF_delete(me->rdfparser);
2398: if (me->target)
2399: (*me->target->isa->abort)(me->target, NULL);
2400: HT_FREE(me);
2401: return HT_ERROR;
2402: }
2403:
2404: PRIVATE int HTRDFTriples_write (HTStream * me, const char * buf, int len)
2405: {
2406: return HT_OK;
2407: }
2408:
2409: PRIVATE int HTRDFTriples_putCharacter (HTStream * me, char c)
2410: {
2411: return HTRDFTriples_write(me, &c, 1);
2412: }
2413:
2414: PRIVATE int HTRDFTriples_putString (HTStream * me, const char * s)
2415: {
2416: return HTRDFTriples_write(me, s, (int) strlen(s));
2417: }
2418:
2419: PRIVATE const HTStreamClass HTRDFTriplesClass =
2420: {
2421: "rdf",
2422: HTRDFTriples_flush,
2423: HTRDFTriples_free,
2424: HTRDFTriples_abort,
2425: HTRDFTriples_putCharacter,
2426: HTRDFTriples_putString,
2427: HTRDFTriples_write
2428: };
2429:
2430: PRIVATE HTStream * RDFParser_new (HTRequest * request,
2431: void * param,
2432: HTFormat input_format,
2433: HTFormat output_format,
2434: HTStream * output_stream)
2435: {
2436: HTStream * me = NULL;
2437: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
2438: HT_OUTOFMEM("HTRDFTriples_new");
2439: me->isa = &HTRDFTriplesClass;
2440: me->state = HT_OK;
2441: me->request = request;
2442: me->target = output_stream ? output_stream : HTErrorStream();
2443:
2444: /* Now create the RDF parser instance */
2445: if ((me->rdfparser = HTRDF_new()) == NULL) {
2446: HT_FREE(me);
2447: return HTErrorStream();
2448: }
2449:
2450: /* Set the source (I guess mostly to follow SiRPAC API) */
2451: {
2452: char * uri = HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
2453: HTRDF_setSource(me->rdfparser, uri);
2454: HT_FREE(uri);
2455: }
2456:
2457: /* Where are we putting data? */
2458: HTRDF_setOutputStream(me->rdfparser, me);
2459:
2460: /* If you want to create Bags, change it to YES */
2461: HTRDF_createBags(me->rdfparser, NO);
2462:
2463: /* Register our new XML Instance handler */
2464: /* @@@ THIS SHOULD BE DONE USING XML NAMESPACE SO THAT WE DON'T CONFLICT @@@ */
2465: HTXMLCallback_registerNew(rdf_newInstance, me->rdfparser);
2466:
2467: HTTRACE(XML_TRACE, "RDF Parser.. Stream created\n");
2468:
2469: return me;
2470: }
2471:
2472: PUBLIC HTStream * HTRDFParser_new (HTRequest * request,
2473: void * param,
2474: HTFormat input_format,
2475: HTFormat output_format,
2476: HTStream * output_stream)
2477: {
2478: return HTXML_new(request, param, input_format, output_format,
2479: RDFParser_new(request, param, input_format, output_format, output_stream));
2480: }
2481:
2482: PRIVATE void triple_newInstance (HTRDF * rdfp, HTTriple * t, void * context)
2483: {
2484: if (rdfp && t) {
2485: HTStream *ostream = rdfp->ostream;
2486: if (ostream) {
2487: PUTC(ostream,'(');
2488: PUTS(ostream, t->m_sPredicate);
2489: PUTC(ostream,',');
2490: PUTS(ostream, t->m_sSubject);
2491: PUTC(ostream,',');
2492: PUTS(ostream, t->m_sObject);
2493: PUTC(ostream,')');
2494: PUTC(ostream,'\n');
2495: }
2496: }
2497: }
2498:
2499: PUBLIC HTStream * HTRDFToTriples (HTRequest * request,
2500: void * param,
2501: HTFormat input_format,
2502: HTFormat output_format,
2503: HTStream * output_stream)
2504: {
2.2 frystyk 2505: HTStream * me = RDFParser_new(request, param, input_format, output_format, output_stream);
2.1 frystyk 2506: HTTRACE(XML_TRACE, "RDF Converter. To Triples\n");
2507:
2508: /* Register our own tripple instance handler */
2509: HTRDF_registerNewTripleCallback(me->rdfparser, triple_newInstance, NULL);
2510:
2511: /* Create an XML parser instance and return */
2512: return HTXML_new(request, param, input_format, output_format, me);
2513: }
2514:
Webmaster