cmXml.h/c : Added cmXmlSearch() functions.

This commit is contained in:
kevin 2015-12-17 16:57:07 -05:00
parent dbd3da490e
commit 59bd46a15f
2 changed files with 189 additions and 34 deletions

184
cmXml.c
View File

@ -11,9 +11,10 @@
#include "cmLinkedHeap.h" #include "cmLinkedHeap.h"
#include "cmFile.h" #include "cmFile.h"
#include "cmXml.h" #include "cmXml.h"
#include "cmText.h"
/* /*
To do: To Do:
1) Escape node data strings and attribute values. 1) Escape node data strings and attribute values.
2) Attribute values must be quoted by they may be quoted with either single or double quotes. 2) Attribute values must be quoted by they may be quoted with either single or double quotes.
3) Consider not buffering the XML file and reading directly from the file. 3) Consider not buffering the XML file and reading directly from the file.
@ -140,29 +141,26 @@ cmXmlNode_t* _cmXmlNodeAlloc( cmXml_t* p, unsigned flags, const cmChar_t* label,
} }
} }
// all new nodes are put on the top of the stack
p->stack = np; p->stack = np;
if( cmIsFlag(flags,kRootXmlFl) ) // all nodes must have a valid 'type' flag
p->root = np; if( (flags & kTypeXmlFlags) == 0 )
else
{
if( cmIsFlag(flags,kDeclXmlFl) )
{
}
else
{
if( cmIsFlag(flags,kDoctypeXmlFl ) )
p->doctype = np;
else
{
if( !cmIsFlag(flags,kNormalXmlFl ) )
{ {
_cmXmlSyntaxError(p); _cmXmlSyntaxError(p);
return NULL; return NULL;
} }
// if this is the root node
if( cmIsFlag(flags,kRootXmlFl) )
{
assert( p->root == NULL );
p->root = np;
} }
}
} // if this is the 'doctype' node
if( cmIsFlag(flags,kDoctypeXmlFl ) )
p->doctype = np;
if( label != NULL ) if( label != NULL )
np->label = cmLhAllocStrN(p->heapH,label,labelN); np->label = cmLhAllocStrN(p->heapH,label,labelN);
@ -711,24 +709,35 @@ cmXmlRC_t cmXmlClear( cmXmlH_t h )
return rc; return rc;
} }
const cmXmlNode_t* cmXmlRoot( cmXmlH_t h )
{
cmXml_t* p = _cmXmlHandleToPtr(h);
return p->root;
}
void _cmXmlPrintNode( const cmXmlNode_t* np, cmRpt_t* rpt, unsigned indent ) void _cmXmlPrintNode( const cmXmlNode_t* np, cmRpt_t* rpt, unsigned indent )
{ {
cmChar_t s[ indent + 1 ]; cmChar_t s[ indent + 1 ];
memset(s,' ',indent); memset(s,' ',indent);
s[indent] = 0; s[indent] = 0;
// print indent and label
cmRptPrintf(rpt,"%s%s: ",s,np->label); cmRptPrintf(rpt,"%s%s: ",s,np->label);
// print this node's attributes
cmXmlAttr_t* ap = np->attr; cmXmlAttr_t* ap = np->attr;
for(; ap!=NULL; ap=ap->link) for(; ap!=NULL; ap=ap->link)
cmRptPrintf(rpt,"%s='%s' ",ap->label,ap->value); cmRptPrintf(rpt,"%s='%s' ",ap->label,ap->value);
// print this nodes data string
if( np->dataStr != NULL ) if( np->dataStr != NULL )
cmRptPrintf(rpt," (%s)",np->dataStr); cmRptPrintf(rpt," (%s)",np->dataStr);
cmRptPrintf(rpt,"\n"); cmRptPrintf(rpt,"\n");
// print this nodes children via recursion
cmXmlNode_t* cnp = np->children; cmXmlNode_t* cnp = np->children;
for(; cnp!=NULL; cnp=cnp->sibling ) for(; cnp!=NULL; cnp=cnp->sibling )
_cmXmlPrintNode(cnp,rpt,indent+2); _cmXmlPrintNode(cnp,rpt,indent+2);
@ -742,6 +751,132 @@ void cmXmlPrint( cmXmlH_t h , cmRpt_t* rpt )
_cmXmlPrintNode(p->root,rpt,0); _cmXmlPrintNode(p->root,rpt,0);
} }
const cmXmlNode_t* cmXmlSearch( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN )
{
// if the 'label' matches this node's label ...
if( cmTextCmp(np->label,label) == 0 )
{
unsigned matchN = 0;
const cmXmlAttr_t* a = np->attr;
unsigned i;
// ... then check for attribute matches also.
for(i=0; i<attrN; ++i)
{
for(; a!=NULL; a=a->link)
{
if( cmTextCmp(a->label,attrV[i].label) == 0 && cmTextCmp(a->value,attrV[i].value) == 0 )
{
++matchN;
// if a match was found for all attributes then the return np as the solution
if( matchN == attrN )
return np;
break;
}
}
}
}
// this node did not match - try each of this nodes children
const cmXmlNode_t* cnp = np->children;
for(; cnp!=NULL; cnp=cnp->sibling)
if(( np = cmXmlSearch(cnp,label,attrV,attrN)) != NULL )
return np; // a child matched
// no match was found.
return NULL;
}
const cmXmlNode_t* cmXmlSearchV( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, va_list vl )
{
while( label != NULL )
{
if((np = cmXmlSearch(np,label,attrV,attrN)) == NULL )
return NULL;
if((label = va_arg(vl,cmChar_t*)) != NULL)
{
attrV = va_arg(vl,const cmXmlAttr_t*);
attrN = va_arg(vl,unsigned);
}
}
return np;
}
const cmXmlNode_t* cmXmlSearchN( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, ... )
{
va_list vl;
va_start(vl,attrN);
np = cmXmlSearchV(np,label,attrV,attrN,vl);
va_end(vl);
return np;
}
cmXmlRC_t cmXmlGetInt( const cmXmlNode_t* np, int* retRef, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, ... )
{
cmXmlRC_t rc = kNodeNotFoundXmlRC;
va_list vl;
va_start(vl,attrN);
// find the requsted node
if((np = cmXmlSearchV(np,label,attrV,attrN,vl)) != NULL )
{
// if the returned node does not have a data string
if( np->dataStr == NULL )
return kInvalidTypeXmlRC;
errno = 0;
// convert the string to an integer
strtol(np->dataStr,NULL,10);
if( errno != 0 )
return kInvalidTypeXmlRC;
rc = kOkXmlRC;
}
va_end(vl);
return rc;
}
void _cmXmlPrintMeasure( const cmXmlNode_t* mnp )
{
}
cmXmlRC_t _cmXmlPrintScore( cmXmlH_t h )
{
cmXmlRC_t rc = kOkXmlRC;
const int sN = 32;
cmChar_t s[sN+1];
unsigned maxMeasNumb = 4;
unsigned i;
cmXml_t* p = _cmXmlHandleToPtr(h);
for(i=0; i<=maxMeasNumb; ++i)
{
snprintf(s,sN,"%i",i);
cmXmlAttr_t aV[] =
{
{ "number",s }
};
const cmXmlNode_t* np;
if((np = cmXmlSearch(cmXmlRoot(h),"measure",aV,1)) == NULL )
return cmErrMsg(&p->err,kTestFailXmlRC,"Missing measure '%i'.",i);
}
return rc;
}
cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn ) cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn )
{ {
@ -754,7 +889,18 @@ cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn )
if((rc = cmXmlParse(h,fn)) != kOkXmlRC ) if((rc = cmXmlParse(h,fn)) != kOkXmlRC )
goto errLabel; goto errLabel;
cmXmlPrint(h,&ctx->rpt); cmXmlAttr_t aV[] =
{
{ "id","P1"}
};
if( cmXmlSearch(cmXmlRoot(h),"part",aV,1) == NULL )
{
cmErrMsg(&ctx->err,kTestFailXmlRC,"Search failed.");
goto errLabel;
}
//cmXmlPrint(h,&ctx->rpt);
errLabel: errLabel:
cmXmlFree(&h); cmXmlFree(&h);

13
cmXml.h
View File

@ -10,8 +10,10 @@ extern "C" {
kOkXmlRC = cmOkRC, kOkXmlRC = cmOkRC,
kMemAllocErrXmlRC, kMemAllocErrXmlRC,
kLHeapXmlRC, kLHeapXmlRC,
kLexErrXmlRC, kSyntaxErrorXmlRC,
kSyntaxErrorXmlRC kTestFailXmlRC,
kInvalidTypeXmlRC,
kNodeNotFoundXmlRC
}; };
typedef struct cmXmlAttr_str typedef struct cmXmlAttr_str
@ -27,6 +29,7 @@ extern "C" {
kDeclXmlFl = 0x0002, kDeclXmlFl = 0x0002,
kDoctypeXmlFl = 0x0004, kDoctypeXmlFl = 0x0004,
kNormalXmlFl = 0x0008, kNormalXmlFl = 0x0008,
kTypeXmlFlags = kRootXmlFl | kDeclXmlFl | kDoctypeXmlFl | kNormalXmlFl,
kClosedXmlFl = 0x0010 kClosedXmlFl = 0x0010
}; };
@ -57,8 +60,14 @@ extern "C" {
cmXmlRC_t cmXmlParse( cmXmlH_t h, const cmChar_t* fn ); cmXmlRC_t cmXmlParse( cmXmlH_t h, const cmChar_t* fn );
cmXmlRC_t cmXmlClear( cmXmlH_t h ); cmXmlRC_t cmXmlClear( cmXmlH_t h );
const cmXmlNode_t* cmXmlRoot( cmXmlH_t h );
void cmXmlPrint( cmXmlH_t h, cmRpt_t* rpt ); void cmXmlPrint( cmXmlH_t h, cmRpt_t* rpt );
const cmXmlNode_t* cmXmlSearch( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN );
cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn ); cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn );
#ifdef __cpluspus #ifdef __cpluspus