source: branches/1.7/src/objects/RpParserXML.cc @ 6705

Last change on this file since 6705 was 5679, checked in by ldelgass, 9 years ago

Full merge 1.3 branch to uq branch to sync. Fixed partial subdirectory merge
by removing mergeinfo from lang/python/Rappture directory.

  • Property svn:eol-style set to native
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.