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