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