source: trunk/src/objects/RpParserXML.cc @ 3177

Last change on this file since 3177 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

File size: 21.9 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture 2.0 XML Parser Object Source
4 *
5 * ======================================================================
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
8 *
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 */
13
14#include <errno.h>
15#include <expat.h>
16#include <string.h>
17#include <stdarg.h>
18#include "RpParserXML.h"
19#include "RpSimpleBuffer.h"
20#include "RpPath.h"
21
22struct Rp_ParserXmlStruct {
23    Rp_Tree tree;
24    Rp_TreeNode curr;
25    Rappture::Path *path;
26    Rappture::SimpleCharBuffer *buf;
27};
28
29const char *Rp_ParserXml_Field_ID = "id";
30const char *Rp_ParserXml_Field_VALUE = "value";
31const char *Rp_ParserXml_Field_VISITED = "visited";
32const char *Rp_ParserXml_TreeRootName = "rapptureTree";
33
34static void XMLCALL
35Rp_ParserXmlStartHandler(
36    void *data,
37    const char *el,
38    const char **attr)
39{
40    Rp_ParserXml *inf = (Rp_ParserXml *) data;
41    size_t i = 0;
42
43    inf->curr = Rp_TreeCreateNode(inf->tree, inf->curr, el, -1);
44
45    // store the attributes in the node
46    while (attr[i] != NULL) {
47        const char *attrName = attr[i++];
48        size_t attrValueLen = strlen(attr[i]);
49        // FIXME: memory leak originating from this new call
50        // I'm not sure where/when the attrValue is deleted yet
51        char *attrValue = new char[attrValueLen+1];
52        strcpy(attrValue,attr[i++]);
53        Rp_TreeSetValue(inf->tree,inf->curr,attrName,(void *)attrValue);
54    }
55    inf->path->add(el);
56}
57
58static void XMLCALL
59Rp_ParserXmlEndHandler(
60    void *data,
61    const char *el)
62{
63    Rp_ParserXml *inf = (Rp_ParserXml *) data;
64
65    if (inf == NULL) {
66        return;
67    }
68
69    char *value = NULL;
70    Rp_TreeGetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,(void **)&value);
71
72    if (value != NULL) {
73        // strip trailing spaces
74        int i = 0;
75        for (i = strlen(value)-1; i >= 0; i--) {
76            if (isspace(value[i])) {
77                value[i] = '\0';
78            } else {
79                break;
80            }
81        }
82
83        // strip leading spaces
84        int j = 0;
85        for (j = 0; j < i; j++) {
86            if (isspace(value[j])) {
87                value[j] = '\0';
88            } else {
89                break;
90            }
91        }
92
93        if (j > 0) {
94            // reallocate the trimmed string
95            char *newValue = new char[i-j+1+1];
96            strcpy(newValue,value+j);
97            Rp_TreeSetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,
98                (void *)newValue);
99            delete[] value;
100            value = NULL;
101        }
102    }
103
104    inf->path->del();
105    inf->curr = Rp_TreeNodeParent(inf->curr);
106}
107
108void
109Rp_ParserXmlDefaultCharHandler(
110    void* data,
111    XML_Char const* s,
112    int len)
113{
114    Rp_ParserXml *inf = (Rp_ParserXml *) data;
115
116    if (inf == NULL) {
117        return;
118    }
119
120    // FIXME: where/when is this deallocated
121    char *d = new char[len+1];
122
123    if ( s != NULL) {
124        strncpy(d,s,len);
125    }
126
127    d[len] = '\0';
128    Rp_TreeSetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,(void *)d);
129}
130
131Rp_ParserXml *
132Rp_ParserXmlCreate()
133{
134    Rp_ParserXml *p = new Rp_ParserXml();
135
136    Rp_TreeCreate(Rp_ParserXml_TreeRootName,&(p->tree));
137    p->curr = Rp_TreeRootNode(p->tree);
138    p->path = new Rappture::Path();
139    p->buf = new Rappture::SimpleCharBuffer();
140
141
142    return p;
143}
144
145void
146Rp_ParserXmlDestroy(Rp_ParserXml **p)
147{
148    if (p == NULL) {
149        return;
150    }
151
152    if (*p == NULL) {
153        return;
154    }
155
156    Rp_TreeReleaseToken((*p)->tree);
157    delete (*p)->buf;
158    delete (*p)->path;
159    delete *p;
160    *p = NULL;
161}
162
163void
164Rp_ParserXmlParse(
165    Rp_ParserXml *p,
166    const char *xml)
167{
168    if (xml == NULL) {
169        return;
170    }
171
172    XML_Parser parser = XML_ParserCreate(NULL);
173    XML_SetUserData(parser,p);
174    XML_SetElementHandler(parser, Rp_ParserXmlStartHandler,
175        Rp_ParserXmlEndHandler);
176    XML_SetDefaultHandlerExpand(parser, Rp_ParserXmlDefaultCharHandler);
177
178    int done = 1;
179    int len = 0;
180
181    len = strlen(xml);
182    if (XML_Parse(parser, xml, len, done) == XML_STATUS_ERROR) {
183        fprintf(stderr, "Parse error at line %lu:\n%s\n",
184                XML_GetCurrentLineNumber(parser),
185                XML_ErrorString(XML_GetErrorCode(parser)));
186        exit(-1);
187    }
188
189    XML_ParserFree(parser);
190
191    // reset the root node
192    p->curr = Rp_TreeFirstChild(Rp_TreeRootNode(p->tree));
193
194    return;
195}
196
197Rp_TreeNode
198Rp_ParserXmlCreateNode(
199    Rp_ParserXml *p,
200    Rp_TreeNode parent,
201    const char *type,
202    const char *id)
203{
204    if (!p->tree || !parent || !type) {
205        fprintf(stderr,"failed to create node because of invalid data\n");
206        return NULL;
207    }
208
209    Rp_TreeNode child = Rp_TreeCreateNode(p->tree, parent, type, -1);
210
211    if (id != NULL) {
212        size_t attrValueLen = strlen(id);
213        // FIXME: memory leak originating from this new call
214        // I'm not sure where/when the attrValue is deleted yet
215        char *attrValue = new char[attrValueLen+1];
216        strcpy(attrValue,id);
217        Rp_TreeSetValue(p->tree,child,Rp_ParserXml_Field_ID,(void *)attrValue);
218    }
219
220    return child;
221}
222
223int
224Rp_ParserXmlNodeIdentify(
225    Rp_ParserXml *p,
226    Rp_TreeNode n,
227    const char *name,
228    const char *id)
229{
230    int criteriaMet = 0;
231    int criteriaTotal = 0;
232
233    if (n) {
234        if (name) {
235            criteriaTotal++;
236            if (strcmp(name,Rp_TreeNodeLabel(n)) == 0) {
237                criteriaMet++;
238            }
239        }
240        if (id) {
241            criteriaTotal++;
242            const char *nodeId = NULL;
243            Rp_TreeGetValue(p->tree,n,Rp_ParserXml_Field_ID,
244                (void **)&nodeId);
245            if (strcmp(id,nodeId) == 0) {
246                criteriaMet++;
247            }
248        }
249    }
250
251    // check if all of the eligable criteria have been met
252    int retVal = 0;
253    if (criteriaMet == criteriaTotal) {
254        retVal = 0;
255    } else {
256        retVal = 1;
257    }
258
259    return retVal;
260
261}
262
263void
264Rp_ParserXmlFindChild(
265    Rp_ParserXml *p,
266    Rp_TreeNode parent,
267    const char *childName,
268    const char *childId,
269    size_t degree,
270    Rp_TreeNode *child,
271    size_t *numFound)
272{
273    // this function is only concerned with the question:
274    // is a node with a matching name, id, and degree a
275    // child of the provided parent node?
276    // if so return it.
277    // this function does not create new nodes.
278
279    if (child == NULL) {
280        return;
281    }
282
283    if (numFound == NULL) {
284        return;
285    }
286
287    *numFound = 0;
288    *child = Rp_TreeFindChild(parent,childName);
289    if (*child == NULL) {
290        // no nodes with the name childName exist
291        return;
292    }
293
294    while (*child != NULL) {
295        if (Rp_ParserXmlNodeIdentify(p,*child,childName,childId) == 0) {
296            // found a child with the correct name and id
297            (*numFound)++;
298            if (degree == *numFound) {
299                // found a node with the correct degree
300                break;
301            }
302        }
303
304        // check the next child for the correct name and id
305        *child = Rp_TreeNextSibling(*child);
306    }
307
308    return;
309}
310
311Rp_TreeNode
312Rp_ParserXmlSearch(
313    Rp_ParserXml *p,
314    const char *path,
315    int create)
316{
317    Rappture::Path pathObj(path);
318    Rp_TreeNode parent = NULL;
319    Rp_TreeNode child = NULL;
320
321    if (p == NULL) {
322        return NULL;
323    }
324
325    // start searching from the base node
326    parent = p->curr;
327
328    // if (path == NULL) return the base node
329    child = p->curr;
330
331    pathObj.first();
332    while ( (!pathObj.eof()) &&
333            (parent != NULL) ) {
334
335        const char *childName = pathObj.type();
336        const char *childId = pathObj.id();
337        size_t childDegree = pathObj.degree();
338
339        size_t foundCnt = 0;
340        Rp_ParserXmlFindChild(p, parent, childName, childId,
341            childDegree, &child, &foundCnt);
342
343        if (child == NULL) {
344            // no nodes with the name childName exist
345            // FIXME: use the RPXML_CREATE flag
346            if (create) {
347                for (size_t i = foundCnt; i < pathObj.degree(); i++) {
348                    child = Rp_ParserXmlCreateNode(p, parent,
349                                childName, childId);
350                    if (child == NULL) {
351                        // error while creating the child node
352                        // signal error
353                        break;
354                    }
355                }
356            } else {
357                // fprintf(stderr,"invalid path %s at %s\n",path,childName);
358                break;
359            }
360        }
361
362        parent = child;
363        pathObj.next();
364    }
365
366    return child;
367}
368
369const char *
370Rp_ParserXmlGet(
371    Rp_ParserXml *p,
372    const char *path)
373{
374    const char *value = NULL;
375    Rp_TreeNode child = NULL;
376
377    child = Rp_ParserXmlSearch(p, path, 0);
378    if (child != NULL) {
379        Rp_TreeGetValue(p->tree,child,Rp_ParserXml_Field_VALUE,(void **)&value);
380    }
381
382    return value;
383}
384
385void
386Rp_ParserXmlPut(
387    Rp_ParserXml *p,
388    const char *path,
389    const char *val,
390    int append)
391{
392    const char *oldval = NULL;
393    char *newval = NULL;
394    size_t oldval_len = 0;
395    size_t val_len = 0;
396
397    if (val == NULL) {
398        // no value, do nothing
399        return;
400    }
401
402    Rp_TreeNode child = Rp_ParserXmlSearch(p, path, 1);
403
404    if (child == NULL) {
405        // error while searching for node?
406        return;
407    }
408
409    // check to see if there is already a value
410    if (RP_OK == Rp_TreeGetValue(p->tree,child,
411                    Rp_ParserXml_Field_VALUE,
412                    (void **)&oldval)) {
413        if (oldval != NULL) {
414            // FIXME: use the RPXML_APPEND flag
415            if (append) {
416                oldval_len = strlen(oldval);
417                val_len = strlen(val);
418                newval = new char[oldval_len + val_len + 1];
419                strncpy(newval,oldval,oldval_len);
420            }
421            // free the old data
422            delete[] oldval;
423            oldval = NULL;
424        }
425    }
426
427    // allocate space for our new value if needed
428    if (newval == NULL) {
429        // set the new value for the node
430        val_len = strlen(val);
431        newval = new char[val_len + 1];
432    }
433
434    strcpy(newval+oldval_len,val);
435
436    // set the value of the child node
437    if (RP_ERROR == Rp_TreeSetValue(p->tree,child,
438                        Rp_ParserXml_Field_VALUE,
439                        (void *)newval)) {
440        fprintf(stderr,"error while setting value of %s\n",path);
441    }
442
443    /*
444    if (p->curr == p->root) {
445        // reset the root node
446        p->curr = Rp_TreeFirstChild(p->root);
447    }
448    */
449
450    return;
451}
452
453void
454Rp_ParserXmlPutF(
455    Rp_ParserXml *p,
456    const char *path,
457    const char *format,
458    ...)
459{
460    if (format == NULL) {
461        // no value, do nothing
462        return;
463    }
464
465    Rp_TreeNode child = Rp_ParserXmlSearch(p, path, 1);
466
467    if (child == NULL) {
468        fprintf(stderr, "child node %s does not exist", path);
469        return;
470    }
471
472    // check to see if there is already a value
473    const char *oldval = NULL;
474    if (RP_OK == Rp_TreeGetValue(p->tree,child,
475                    Rp_ParserXml_Field_VALUE,
476                    (void **)&oldval)) {
477        if (oldval != NULL) {
478            // free the old data
479            delete[] oldval;
480            oldval = NULL;
481        }
482    }
483
484    // store the formatted string in the tree node
485    size_t stackSize = 1024;
486    char *stackSpace = new char[stackSize];
487    va_list lst;
488    size_t n;
489
490    va_start(lst, format);
491    n = vsnprintf(stackSpace, stackSize, format, lst);
492    if (n >= stackSize) {
493        delete[] stackSpace;
494        stackSpace = new char[n];
495        vsnprintf(stackSpace, n, format, lst);
496    }
497
498    // set the value of the child node
499    if (RP_ERROR == Rp_TreeSetValue(p->tree,child,
500                        Rp_ParserXml_Field_VALUE,
501                        (void *)stackSpace)) {
502        fprintf(stderr,"error while setting value of %s\n",path);
503    }
504
505    /*
506    if (p->curr == p->root) {
507        // reset the root node
508        p->curr = Rp_TreeFirstChild(p->root);
509    }
510    */
511
512    return;
513}
514
515void
516Rp_ParserXmlAppendF(
517    Rp_ParserXml *p,
518    const char *path,
519    const char *format,
520    ...)
521{
522    if (format == NULL) {
523        // no value, do nothing
524        return;
525    }
526
527    Rp_TreeNode child = Rp_ParserXmlSearch(p, path, 1);
528
529    if (child == NULL) {
530        fprintf(stderr, "child node %s does not exist", path);
531        return;
532    }
533
534    // check to see if there is already a value
535    const char *oldval = NULL;
536    Rp_TreeGetValue(p->tree,child, Rp_ParserXml_Field_VALUE, (void **)&oldval);
537
538    // get the formatted string
539    size_t stackSize = 1024;
540    char *stackSpace = new char[stackSize];
541    va_list lst;
542    size_t n;
543
544    va_start(lst, format);
545    n = vsnprintf(stackSpace, stackSize, format, lst);
546    if (n >= stackSize) {
547        delete[] stackSpace;
548        stackSpace = new char[n];
549        vsnprintf(stackSpace, n, format, lst);
550    }
551
552    // concatenate the formatted string and the old value
553    char *newval = stackSpace;
554    if (oldval != NULL) {
555        size_t oldval_len = strlen(oldval);
556        newval = new char[n+oldval_len+1];
557        strcpy(newval, oldval);
558        strcat(newval,stackSpace);
559        // free the old data
560        delete[] oldval;
561        oldval = NULL;
562        delete[] stackSpace;
563        stackSpace = NULL;
564    }
565
566    // set the value of the child node
567    if (RP_ERROR == Rp_TreeSetValue(p->tree,child,
568                        Rp_ParserXml_Field_VALUE,
569                        (void *)newval)) {
570        fprintf(stderr,"error while setting value of %s\n",path);
571    }
572
573    /*
574    if (p->curr == p->root) {
575        // reset the root node
576        p->curr = Rp_TreeFirstChild(p->root);
577    }
578    */
579
580    return;
581}
582
583
584Rp_Tree
585Rp_ParserXmlTreeClient(
586    Rp_ParserXml *p)
587{
588    if (p == NULL) {
589        return NULL;
590    }
591    Rp_Tree newTree = NULL;
592    // create a new token for the tree and return it to the caller
593    Rp_TreeGetTokenFromToken(p->tree,&newTree);
594    return newTree;
595}
596
597int
598printXmlData(
599    Rp_TreeNode node,
600    ClientData clientData,
601    int order)
602{
603    Rp_ParserXml *p = (Rp_ParserXml *) clientData;
604
605    Rappture::Path labelComp(Rp_TreeNodeLabel(node));
606    const char *label = labelComp.type();
607    const char *value = NULL;
608
609    size_t width = (Rp_TreeNodeDepth(p->tree,node)-1)*PARSERXML_LEVEL_WIDTH;
610    const char *sp = "";
611    int *visited = NULL;
612
613    Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VALUE,(void **)&value);
614    size_t valLen = 0;
615    if (value != NULL) {
616        valLen = strlen(value);
617    }
618
619    if (!Rp_TreeValueExists(p->tree,node,Rp_ParserXml_Field_VISITED)) {
620        visited = new int();
621        *visited = 0;
622
623        p->buf->appendf("%3$*2$s<%1$s",label,width,sp);
624
625        // go through all attributes and place them in the tag
626        Rp_TreeKey attrName = NULL;
627        Rp_TreeKeySearch search;
628        attrName = Rp_TreeFirstKey (p->tree, node, &search);
629        while (attrName) {
630            if ((*Rp_ParserXml_Field_VALUE != *attrName) &&
631                (strcmp(Rp_ParserXml_Field_VALUE,attrName) != 0)) {
632                const char *attrValue = NULL;
633                Rp_TreeGetValueByKey(p->tree,node,attrName,(void**)&attrValue);
634                p->buf->appendf(" %s=\"%s\"",attrName,attrValue);
635            }
636            attrName = Rp_TreeNextKey(p->tree, &search);
637        }
638
639        // close the opening tag
640        p->buf->appendf(">");
641
642        // append the value of the tag if any
643        if ( (value != NULL ) &&
644             (valLen != 0) ) {
645            p->buf->appendf("%s",value);
646        } else {
647            p->buf->appendf("\n");
648        }
649
650        // set the "visited" temporary flag so the next time
651        // we encounter this node, we know it is as a closing node
652        Rp_TreeSetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void *)visited);
653
654    } else {
655        Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void **)&visited);
656        delete visited;
657        Rp_TreeUnsetValue(p->tree,node,Rp_ParserXml_Field_VISITED);
658        if ( (value != NULL ) &&
659             (valLen != 0) ) {
660            p->buf->appendf("</%s>\n",label);
661        } else {
662            p->buf->appendf("%3$*2$s</%1$s>\n",label,width,sp);
663        }
664
665    }
666
667    return RP_OK;
668}
669
670const char *
671Rp_ParserXmlXml(
672    Rp_ParserXml *p)
673{
674    p->buf->clear();
675    p->buf->appendf("<?xml version=\"1.0\"?>\n");
676
677    Rp_TreeNode root = Rp_TreeRootNode(p->tree);
678    if (p->curr == root) {
679        // reset the root node
680        root = Rp_TreeFirstChild(root);
681    } else {
682        root = p->curr;
683    }
684
685    Rp_TreeApplyDFS(root, printXmlData, (ClientData)p, TREE_PREORDER|TREE_POSTORDER);
686
687    return p->buf->bytes();
688}
689
690int
691printPathVal(
692    Rp_TreeNode node,
693    ClientData clientData,
694    int order)
695{
696    Rp_ParserXml *p = (Rp_ParserXml *) clientData;
697
698    int *visited = NULL;
699
700    if (!Rp_TreeValueExists(p->tree,node,Rp_ParserXml_Field_VISITED)) {
701        // update path
702        p->path->add(Rp_TreeNodeLabel(node));
703
704        const char *id = NULL;
705        if (RP_OK == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_ID,(void **)&id)) {
706            p->path->last();
707            p->path->id(id);
708        }
709
710        const char *value = NULL;
711        if (RP_ERROR == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VALUE,(void **)&value)) {
712            // error while getting value, exit fxn gracefully?
713            // FIXME: add error code here
714        }
715
716        // append the path and value of the node to our result text
717        if (value && (strlen(value) != 0)) {
718            p->buf->appendf("%s %s\n",p->path->path(),value);
719        }
720
721        // set the "visited" temporary flag so the next time
722        // we encounter this node, we know it is as a closing node
723        visited = new int();
724        *visited = 0;
725        if (RP_ERROR == Rp_TreeSetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void *)visited)) {
726            // FIXME: error while setting value
727        }
728    } else {
729        // update path
730        p->path->del();
731
732        // delete the "visited" temporary flag from the node
733        if (RP_ERROR == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void **)&visited)) {
734            // FIXME: error while getting value
735        }
736        delete visited;
737        if (RP_ERROR == Rp_TreeUnsetValue(p->tree,node,Rp_ParserXml_Field_VISITED)) {
738            // FIXME: error while unsetting value
739        }
740    }
741
742    return RP_OK;
743}
744
745const char *
746Rp_ParserXmlPathVal(
747    Rp_ParserXml *p)
748{
749    p->buf->clear();
750
751    // temporarily store p->path so we can use p as ClientData
752    Rappture::Path *tmpPath = p->path;
753    p->path = new Rappture::Path();
754
755    // Rp_TreeNode root = p->curr;
756    Rp_TreeNode root = Rp_TreeRootNode(p->tree);
757    if (p->curr == root) {
758        // reset the root node
759        root = Rp_TreeFirstChild(root);
760    } else {
761        root = p->curr;
762    }
763
764    Rp_TreeApplyDFS(root, printPathVal, (ClientData)p, TREE_PREORDER|TREE_POSTORDER);
765
766    // restore the original path
767    delete p->path;
768    p->path = tmpPath;
769
770    return p->buf->bytes();
771}
772
773Rp_TreeNode
774Rp_ParserXmlElement(
775    Rp_ParserXml *p,
776    const char *path)
777{
778    if (p == NULL) {
779        return NULL;
780    }
781
782    return Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
783}
784
785Rp_TreeNode
786Rp_ParserXmlParent(
787    Rp_ParserXml *p,
788    const char *path)
789{
790    if (p == NULL) {
791        return NULL;
792    }
793
794    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
795    if (node == NULL) {
796        return NULL;
797    }
798
799    return Rp_TreeNodeParent(node);
800}
801
802size_t
803Rp_ParserXmlChildren(
804    Rp_ParserXml *p,
805    const char *path,
806    const char *type,
807    Rp_Chain *children)
808{
809    size_t count = 0;
810
811    if (p == NULL) {
812        return count;
813    }
814
815    if (children == NULL) {
816        return count;
817    }
818
819    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
820
821    if (node == NULL) {
822        return count;
823    }
824
825    if (type == NULL) {
826        node = Rp_TreeFirstChild(node);
827        while (node != NULL) {
828            count++;
829            Rp_ChainAppend(children,(void*)node);
830            node = Rp_TreeNextSibling(node);
831        }
832    } else {
833        node = Rp_TreeFindChild(node,type);
834        while (node != NULL) {
835            count++;
836            Rp_ChainAppend(children,(void*)node);
837            node = Rp_TreeFindChildNext(node,type);
838        }
839    }
840
841    return count;
842}
843
844size_t
845Rp_ParserXmlNumberChildren(
846    Rp_ParserXml *p,
847    const char *path,
848    const char *type)
849{
850    size_t count = 0;
851
852    if (p == NULL) {
853        return count;
854    }
855
856    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
857    if (node != NULL) {
858        node = Rp_TreeFindChild(node,type);
859        while (node != NULL) {
860            count++;
861            node = Rp_TreeFindChildNext(node,type);
862        }
863    }
864
865    return count;
866}
867
868void
869Rp_ParserXmlBaseNode(
870    Rp_ParserXml *p,
871    Rp_TreeNode node)
872{
873    if (p != NULL) {
874        if (node == NULL) {
875            p->curr = Rp_TreeFirstChild(Rp_TreeRootNode(p->tree));
876        } else {
877            p->curr = node;
878        }
879    }
880}
881
882const char *
883Rp_ParserXmlNodePath(
884    Rp_ParserXml *p,
885    Rp_TreeNode node)
886{
887    Rappture::Path pathObj;
888
889    const char *type = NULL;
890    const char *id = NULL;
891
892    if (p != NULL) {
893        while (node != NULL) {
894            type = Rp_TreeNodeLabel(node);
895            pathObj.parent(type);
896            if (RP_OK == Rp_TreeGetValue(p->tree,node,
897                            Rp_ParserXml_Field_ID,(void **)&id)) {
898                pathObj.id(id);
899            }
900            node = Rp_TreeNodeParent(node);
901        }
902    }
903
904    // remove the tree name from the path
905    pathObj.first();
906    pathObj.del();
907    // remove the <run> tag from the path
908    // pathObj.del();
909
910    p->path->path(pathObj.path());
911    return p->path->path();
912}
913
914const char *
915Rp_ParserXmlNodeId(
916    Rp_ParserXml *p,
917    Rp_TreeNode node)
918{
919    const char *id = NULL;
920    if (p != NULL) {
921        if (node != NULL) {
922            Rp_TreeGetValue(p->tree,node, Rp_ParserXml_Field_ID,(void **)&id);
923        }
924    }
925    return id;
926}
927
928// -------------------------------------------------------------------- //
929
Note: See TracBrowser for help on using the repository browser.