Переглянути джерело

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

master
kevin 9 роки тому
джерело
коміт
59bd46a15f
2 змінених файлів з 189 додано та 34 видалено
  1. 175
    29
      cmXml.c
  2. 14
    5
      cmXml.h

+ 175
- 29
cmXml.c Переглянути файл

@@ -11,9 +11,10 @@
11 11
 #include "cmLinkedHeap.h"
12 12
 #include "cmFile.h"
13 13
 #include "cmXml.h"
14
+#include "cmText.h"
14 15
 
15 16
 /*
16
-To do:
17
+To Do:
17 18
 1) Escape node data strings and attribute values.
18 19
 2) Attribute values must be quoted by they may be quoted with either single or double quotes.
19 20
 3) Consider not buffering the XML file and reading directly from the file.
@@ -131,38 +132,35 @@ cmXmlNode_t* _cmXmlNodeAlloc( cmXml_t* p, unsigned flags, const cmChar_t* label,
131 132
     else
132 133
     {
133 134
       cmXmlNode_t* n0p = NULL;
134
-    cmXmlNode_t* n1p = p->stack->children;
135
+      cmXmlNode_t* n1p = p->stack->children;
135 136
     
136
-    for(; n1p != NULL; n1p=n1p->sibling )
137
-      n0p = n1p;
137
+      for(; n1p != NULL; n1p=n1p->sibling )
138
+        n0p = n1p;
138 139
     
139
-    n0p->sibling = np;    
140
+      n0p->sibling = np;    
140 141
     }
141 142
   }
142
-  
143
+
144
+  // all new nodes are put on the top of the stack
143 145
   p->stack = np;
144
-    
146
+
147
+  // all nodes must have a valid 'type' flag
148
+  if( (flags & kTypeXmlFlags) == 0 )
149
+  {
150
+    _cmXmlSyntaxError(p);
151
+    return NULL;
152
+  }
153
+  
154
+  // if this is the root node
145 155
   if( cmIsFlag(flags,kRootXmlFl) )
146
-    p->root = np;
147
-  else
148 156
   {
149
-    if( cmIsFlag(flags,kDeclXmlFl) )
150
-    {
151
-    }
152
-    else
153
-    {
154
-      if( cmIsFlag(flags,kDoctypeXmlFl ) )
155
-        p->doctype = np;
156
-      else
157
-      {
158
-        if( !cmIsFlag(flags,kNormalXmlFl ) )
159
-        {
160
-          _cmXmlSyntaxError(p);
161
-          return NULL;
162
-        }
163
-      }
164
-    }
157
+    assert( p->root == NULL );
158
+    p->root = np;
165 159
   }
160
+
161
+  // if this is the 'doctype' node
162
+  if( cmIsFlag(flags,kDoctypeXmlFl ) )
163
+    p->doctype = np;
166 164
   
167 165
   if( label != NULL )
168 166
     np->label = cmLhAllocStrN(p->heapH,label,labelN);
@@ -674,8 +672,8 @@ cmXmlRC_t _cmXmlReadNode( cmXml_t* p, cmXmlNode_t* parent )
674 672
 
675 673
 cmXmlRC_t cmXmlParse( cmXmlH_t h, const cmChar_t* fn )
676 674
 {
677
-  cmXmlRC_t rc = kOkXmlRC;
678
-  cmXml_t*  p  = _cmXmlHandleToPtr(h);
675
+  cmXmlRC_t    rc = kOkXmlRC;
676
+  cmXml_t*     p  = _cmXmlHandleToPtr(h);
679 677
   cmXmlNode_t* np = NULL;
680 678
   
681 679
   cmLHeapClear( p->heapH, false );
@@ -711,24 +709,35 @@ cmXmlRC_t cmXmlClear( cmXmlH_t h )
711 709
   return rc;
712 710
 }
713 711
 
712
+const cmXmlNode_t* cmXmlRoot( cmXmlH_t h )
713
+{
714
+  cmXml_t*  p  = _cmXmlHandleToPtr(h);
715
+  return p->root;
716
+}
717
+
718
+
714 719
 void _cmXmlPrintNode( const cmXmlNode_t* np, cmRpt_t* rpt, unsigned indent )
715 720
 {
716 721
   cmChar_t s[ indent + 1 ];
717 722
   memset(s,' ',indent);
718 723
   s[indent] = 0;
724
+
725
+  // print indent and label
719 726
   cmRptPrintf(rpt,"%s%s: ",s,np->label);
720 727
 
728
+  // print this node's attributes
721 729
   cmXmlAttr_t* ap = np->attr;
722 730
   for(; ap!=NULL; ap=ap->link)
723 731
     cmRptPrintf(rpt,"%s='%s' ",ap->label,ap->value);
724 732
 
733
+  // print this nodes data string
725 734
   if( np->dataStr != NULL )
726 735
     cmRptPrintf(rpt," (%s)",np->dataStr);
727 736
 
728 737
   cmRptPrintf(rpt,"\n");
729 738
 
739
+  // print this nodes children via recursion
730 740
   cmXmlNode_t* cnp = np->children;
731
-
732 741
   for(; cnp!=NULL; cnp=cnp->sibling )
733 742
     _cmXmlPrintNode(cnp,rpt,indent+2);
734 743
 
@@ -742,6 +751,132 @@ void      cmXmlPrint( cmXmlH_t h , cmRpt_t* rpt )
742 751
     _cmXmlPrintNode(p->root,rpt,0);
743 752
 }
744 753
 
754
+const cmXmlNode_t* cmXmlSearch( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN )
755
+{
756
+  // if the 'label' matches this node's label ...
757
+  if( cmTextCmp(np->label,label) == 0 )
758
+  {
759
+    unsigned           matchN = 0;
760
+    const cmXmlAttr_t* a      = np->attr;
761
+    unsigned           i;
762
+    
763
+    // ... then check for attribute matches also.
764
+    for(i=0; i<attrN; ++i)
765
+    {
766
+      for(; a!=NULL; a=a->link)
767
+      {
768
+        if( cmTextCmp(a->label,attrV[i].label) == 0 && cmTextCmp(a->value,attrV[i].value) == 0 )
769
+        {
770
+          ++matchN;
771
+
772
+          // if a match was found for all attributes then the return np as the solution
773
+          if( matchN == attrN )
774
+            return np;
775
+          
776
+          break;
777
+        }
778
+      }
779
+    }    
780
+  }
781
+
782
+  // this node did not match - try each of this nodes children
783
+  const cmXmlNode_t* cnp = np->children;
784
+  for(; cnp!=NULL; cnp=cnp->sibling)
785
+    if(( np = cmXmlSearch(cnp,label,attrV,attrN)) != NULL )
786
+      return np;  // a child matched 
787
+
788
+  // no match was found.
789
+  return NULL; 
790
+}
791
+
792
+const cmXmlNode_t* cmXmlSearchV( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, va_list vl )
793
+{
794
+
795
+  while( label != NULL  )
796
+  {
797
+    if((np = cmXmlSearch(np,label,attrV,attrN)) == NULL )
798
+      return NULL;
799
+
800
+    if((label = va_arg(vl,cmChar_t*)) != NULL)
801
+    {
802
+      attrV = va_arg(vl,const cmXmlAttr_t*);
803
+      attrN = va_arg(vl,unsigned);
804
+    }
805
+
806
+  }
807
+  
808
+  return np;
809
+}
810
+
811
+const cmXmlNode_t* cmXmlSearchN( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, ... )
812
+{
813
+  va_list vl;
814
+  va_start(vl,attrN);
815
+  np = cmXmlSearchV(np,label,attrV,attrN,vl);
816
+  va_end(vl);
817
+  return np;
818
+}
819
+
820
+cmXmlRC_t cmXmlGetInt( const cmXmlNode_t* np, int* retRef, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN, ... )
821
+{
822
+  cmXmlRC_t          rc = kNodeNotFoundXmlRC;
823
+  va_list            vl;
824
+  
825
+  va_start(vl,attrN);
826
+
827
+  // find the requsted node
828
+  if((np = cmXmlSearchV(np,label,attrV,attrN,vl)) != NULL )
829
+  {
830
+    // if the returned node does not have a data string
831
+    if( np->dataStr == NULL )      
832
+      return kInvalidTypeXmlRC;
833
+
834
+    errno = 0;
835
+
836
+    // convert the string to an integer
837
+    strtol(np->dataStr,NULL,10);
838
+    
839
+    if( errno != 0 )
840
+      return kInvalidTypeXmlRC;
841
+    
842
+    rc = kOkXmlRC;
843
+  }
844
+  
845
+  va_end(vl);
846
+  
847
+  return rc;
848
+}
849
+
850
+
851
+void _cmXmlPrintMeasure( const cmXmlNode_t* mnp )
852
+{
853
+}
854
+
855
+cmXmlRC_t _cmXmlPrintScore( cmXmlH_t h )
856
+{
857
+  cmXmlRC_t rc          = kOkXmlRC;
858
+  const int sN          = 32;
859
+  cmChar_t  s[sN+1];
860
+  unsigned  maxMeasNumb = 4;
861
+  unsigned  i;
862
+  cmXml_t*  p           = _cmXmlHandleToPtr(h);
863
+  
864
+  for(i=0; i<=maxMeasNumb; ++i)
865
+  {
866
+    snprintf(s,sN,"%i",i);
867
+    cmXmlAttr_t aV[] =
868
+    {
869
+      { "number",s }
870
+    };
871
+
872
+    const cmXmlNode_t* np;
873
+    if((np = cmXmlSearch(cmXmlRoot(h),"measure",aV,1)) == NULL )
874
+      return cmErrMsg(&p->err,kTestFailXmlRC,"Missing measure '%i'.",i);
875
+  }
876
+
877
+  return rc;
878
+}
879
+
745 880
 
746 881
 cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn )
747 882
 {
@@ -754,7 +889,18 @@ cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn )
754 889
   if((rc = cmXmlParse(h,fn)) != kOkXmlRC )
755 890
     goto errLabel;
756 891
 
757
-  cmXmlPrint(h,&ctx->rpt);
892
+  cmXmlAttr_t aV[] =
893
+  {
894
+    { "id","P1"}
895
+  };
896
+
897
+  if( cmXmlSearch(cmXmlRoot(h),"part",aV,1) == NULL )
898
+  {
899
+    cmErrMsg(&ctx->err,kTestFailXmlRC,"Search failed.");
900
+    goto errLabel;
901
+  }
902
+  
903
+  //cmXmlPrint(h,&ctx->rpt);
758 904
 
759 905
  errLabel:
760 906
   cmXmlFree(&h);

+ 14
- 5
cmXml.h Переглянути файл

@@ -10,8 +10,10 @@ extern "C" {
10 10
     kOkXmlRC = cmOkRC,
11 11
     kMemAllocErrXmlRC,
12 12
     kLHeapXmlRC,
13
-    kLexErrXmlRC,
14
-    kSyntaxErrorXmlRC
13
+    kSyntaxErrorXmlRC,
14
+    kTestFailXmlRC,
15
+    kInvalidTypeXmlRC,
16
+    kNodeNotFoundXmlRC
15 17
   }; 
16 18
   
17 19
   typedef struct cmXmlAttr_str
@@ -27,6 +29,7 @@ extern "C" {
27 29
     kDeclXmlFl    = 0x0002,
28 30
     kDoctypeXmlFl = 0x0004,
29 31
     kNormalXmlFl  = 0x0008,
32
+    kTypeXmlFlags = kRootXmlFl | kDeclXmlFl | kDoctypeXmlFl | kNormalXmlFl,    
30 33
     kClosedXmlFl  = 0x0010
31 34
   };
32 35
   
@@ -55,9 +58,15 @@ extern "C" {
55 58
   cmXmlRC_t cmXmlFree(  cmXmlH_t* hh );
56 59
   bool      cmXmlIsValid( cmXmlH_t h );
57 60
   
58
-  cmXmlRC_t cmXmlParse( cmXmlH_t h, const cmChar_t* fn );
59
-  cmXmlRC_t cmXmlClear( cmXmlH_t h );
60
-  void      cmXmlPrint( cmXmlH_t h , cmRpt_t* rpt );
61
+  cmXmlRC_t          cmXmlParse( cmXmlH_t h, const cmChar_t* fn );
62
+  cmXmlRC_t          cmXmlClear( cmXmlH_t h );
63
+  const cmXmlNode_t* cmXmlRoot(  cmXmlH_t h );
64
+  void               cmXmlPrint( cmXmlH_t h, cmRpt_t* rpt );
65
+
66
+  const cmXmlNode_t* cmXmlSearch( const cmXmlNode_t* np, const cmChar_t* label, const cmXmlAttr_t* attrV, unsigned attrN );
67
+
68
+  
69
+  
61 70
 
62 71
   cmXmlRC_t cmXmlTest( cmCtx_t* ctx, const cmChar_t* fn );
63 72
   

Завантаження…
Відмінити
Зберегти