source: branches/ali/GDE/PHYML20130708/phyml/src/xml.c

Last change on this file was 10307, checked in by aboeckma, 11 years ago

added most recent version of phyml

File size: 27.1 KB
Line 
1#include "xml.h"
2
3//////////////////////////////////////////////////////////////
4//////////////////////////////////////////////////////////////
5
6xml_node *XML_Load_File(FILE *fp)
7{
8  int c;
9  char *buffer,*bufptr;
10  int bufsize;
11  xml_node *parent,*node;
12
13  buffer = (char *)mCalloc(T_MAX_XML_TAG,sizeof(char));
14
15  bufsize = T_MAX_XML_TAG;
16  bufptr  = buffer;
17  parent  = NULL;
18  node    = NULL;
19
20  while((c = fgetc(fp)) != EOF)
21    {
22      if(c == '<' && bufptr > buffer) 
23        {
24          *bufptr = '\0';
25
26          /* PhyML_Printf("\n. Read value '%s' for node '%s'",buffer,node->name); */
27          /* fflush(NULL); */
28
29          XML_Set_Node_Value(node,buffer);
30          bufptr = buffer;
31        }
32             
33      if(c == '<')
34        {
35          bufptr = buffer;
36
37          while((c = fgetc(fp)) != EOF)
38            {
39              if(isspace(c) != NO || c == '>' || (c == '/' && bufptr > buffer)) break; // End of open or close tag
40              else if(c == '<')
41                {
42                  Exit("\n== Bare < in element!");
43                }             
44              else if(XML_Add_Character(c,&bufptr,&buffer,&bufsize))
45                {
46                  PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
47                  Exit("\n");     
48                }
49            }
50
51          *bufptr = '\0';
52         
53          if(!strcmp(buffer,"!--")) // Get the rest of the comment
54            {
55              while((c = fgetc(fp)) != EOF)
56                {
57                 
58                  if(c == '>' && bufptr > (buffer + 4) && bufptr[-3] != '-' &&
59                     bufptr[-2] == '-' && bufptr[-1] == '-') break;
60                  else if(XML_Add_Character(c,&bufptr,&buffer,&bufsize))
61                    {
62                      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
63                      Exit("\n");         
64                    }
65                }
66              *bufptr = '\0';
67
68              if(c != '>')
69                {
70                  PhyML_Printf("\n== Early EOF in comment node.");
71                  Exit("\n");     
72                }             
73            }     
74          else if(buffer[0] == '/') // Close tag
75            {
76              if(strcmp(buffer+1,parent->name))
77                {
78                  PhyML_Printf("\n== Opened tag with name '%s' and closed it with '%s'...",node->name,buffer+1);
79                  PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
80                  Exit("\n");
81                }
82
83              /* printf("\n. Closing node with name '%s'",node->name); */
84
85              if(node->parent)
86                {
87                  parent = parent->parent;
88                  node   = parent;
89                }
90            }
91          else if(buffer[0] == '?')
92            {
93              while((c = fgetc(fp)) != EOF)
94                {
95                  if (c == '>' && bufptr > buffer && bufptr[-1] == '?')
96                    break;
97                  else if (XML_Add_Character(c, &bufptr, &buffer, &bufsize))
98                    {
99                      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
100                      Exit("\n");         
101                    }
102                }
103
104              if(c != '>')
105                {
106                  PhyML_Printf("\n== An error occurred when reading the processing instruction.");
107                  PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
108                  Exit("\n");     
109                }
110
111              *bufptr = '\0';
112
113            }
114          else // Open tag
115            {
116              node = XML_Make_Node(buffer);
117              XML_Init_Node(parent,node,buffer);
118              if(!parent) parent = node;
119
120              if(isspace(c) != NO) c=XML_Parse_Element(fp,node);
121              else if(c == '/')
122                {
123                  if((c=fgetc(fp)) != '>')
124                    {
125                      PhyML_Printf("\n== Expected '>' but read '%c' instead",c);
126                      Exit("\n");
127                    }
128                  c = '/';
129                }
130
131              if(c != '/') parent = node;
132
133              buffer[0] = '\0';
134            }     
135          bufptr = buffer;
136        }
137      else if(isspace(c) == NO)
138        {
139          if(XML_Add_Character(c,&bufptr,&buffer,&bufsize))
140            {
141              PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
142              Exit("\n");
143            }
144        }
145    }
146  Free(buffer);
147  return node;
148}
149
150//////////////////////////////////////////////////////////////
151//////////////////////////////////////////////////////////////
152
153int XML_Add_Character(int c, char  **bufptr, char **buffer, int *bufsize)
154{
155  char *newbuffer;
156
157  if(*bufptr >= (*buffer + *bufsize - 4))
158    {
159      // Increase the size of the buffer...
160     
161      if (*bufsize < 1024)
162        (*bufsize) *= 2;
163      else
164        (*bufsize) += 1024;
165
166    if((newbuffer = realloc(*buffer, *bufsize)) == NULL)
167      {
168        Free(*buffer);
169        PhyML_Printf("\n== Unable to expand string buffer to %d bytes!", *bufsize);
170        Exit("\n");
171      }
172   
173    *bufptr = newbuffer + (*bufptr - *buffer);
174    *buffer = newbuffer;
175  }
176
177  /* *(*bufptr)++ = tolower(c); */
178  *(*bufptr)++ = c;
179  return 0;
180}
181
182//////////////////////////////////////////////////////////////
183//////////////////////////////////////////////////////////////
184
185int XML_Parse_Element(FILE *fp, xml_node *n)
186{
187  int c;
188  int quote;
189  char *name, *value, *ptr;
190  int namesize, valsize;
191
192  name  = (char *)mCalloc(64,sizeof(char));
193  value = (char *)mCalloc(64,sizeof(char));
194 
195  namesize = 64;
196  valsize  = 64;
197 
198  while((c = fgetc(fp)) != EOF)
199    {
200
201      if(isspace(c) != NO) continue;
202
203      if(c == '/') // End of tag
204        {
205          /* printf("\n. Closing node '%s'.",n->name); */
206
207          quote = fgetc(fp);
208          if(quote != '>')
209            {
210              PhyML_Printf("\n== Expected '>' after '%c' but read '%c' instead",c,quote);
211              Exit("\n");
212            }
213          break;
214        }
215      else if(c == '<')
216        {
217          Exit("\n== Bare < in element!");       
218        }
219      else if(c == '>') // End of tag
220        {
221          break;
222        }
223
224      name[0] = c;
225      ptr     = name + 1;
226
227      if(c == '\"' || c == '\'') // Name is in quotes
228        {
229          quote = c;
230
231          while((c = fgetc(fp)) != EOF)
232            {
233              if(XML_Add_Character(c,&ptr,&name,&namesize))
234                {
235                  PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
236                  Exit("\n");
237                }
238              if(c == quote) break;
239            }     
240        }
241      else // Name not in quotes
242        {
243          while((c = fgetc(fp)) != EOF)
244            {
245              if(isspace(c) != NO || c == '=' || c == '/' || c == '>' || c == '?')
246                break;
247              else
248                {
249                  if(XML_Add_Character(c,&ptr,&name,&namesize))
250                    {
251                      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
252                      Exit("\n");
253                    }
254                }         
255            }
256        }
257     
258      *ptr = '\0';
259           
260      while(c != EOF && isspace(c) != NO) c = fgetc(fp);
261
262      if(c == '=') // Read the attribute value
263        {
264          while((c = fgetc(fp)) != EOF && isspace(c) != NO);
265
266          if(c == EOF)
267            {
268              PhyML_Printf("\n== Missing value in attribute.");
269              PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
270              Exit("\n");
271            }
272
273          if(c == '\'' || c == '\"')
274            {
275              quote = c;
276              ptr   = value;
277
278              while((c = fgetc(fp)) != EOF)
279                {
280                  if(c == quote) break;
281                  else
282                    {
283                      if(XML_Add_Character(c,&ptr,&value,&valsize))
284                        {
285                          PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
286                          Exit("\n");
287                        }
288                    }
289                }
290              *ptr = '\0';
291            }
292          else
293            {
294              value[0] = c;
295              ptr      = value + 1;
296             
297              while((c = fgetc(fp)) != EOF)
298                {
299                  if(isspace(c) != NO || c == '=' || c == '/' || c == '>')
300                    break;
301                  else
302                    {
303                      if(XML_Add_Character(c,&ptr,&value,&valsize))
304                        {
305                          PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
306                          Exit("\n");
307                        }                     
308                    }
309                }             
310            }
311        }
312
313      /* printf("\n. Setting attribute '%s=%s' to node '%s'",name,value,n->name); */
314      XML_Set_Attribute(n,name,value);
315
316      if(c == '>') break;
317
318
319    }
320  Free(name);
321  Free(value);
322
323  /* printf("\n. Return '%c'\n",c); */
324  return(c);
325}
326
327//////////////////////////////////////////////////////////////
328//////////////////////////////////////////////////////////////
329
330xml_attr *XML_Search_Attribute(xml_node *n, char *target_attr_name)
331{
332  xml_attr *attr;
333
334  attr = n->attr;
335  do
336    {
337      if(!strcmp(attr->name,target_attr_name)) return attr;
338      attr = attr->next;
339    }
340  while(attr);
341
342  return(NULL);
343}
344
345//////////////////////////////////////////////////////////////
346//////////////////////////////////////////////////////////////
347
348int XML_Set_Attribute(xml_node *n, char *attr_name, char *attr_value)
349{
350  xml_attr *prev;
351  char *s;
352
353  prev = NULL;
354  while(n->attr != NULL) 
355    {
356      prev    = n->attr;
357      n->attr = n->attr->next;
358    }
359
360  n->attr = XML_Make_Attribute(prev,attr_name,attr_value);
361  XML_Init_Attribute(n->attr);
362  n->n_attr++;
363
364  // rewind
365  while(n->attr->prev != NULL) n->attr = n->attr->prev; 
366
367  s = To_Lower_String(attr_name);
368  if(!strcmp(s,"id"))
369    {
370      XML_Set_Node_Id(n,attr_value);
371      /* printf("\n. Node '%s' id is '%s'",n->name,n->id); */
372    }
373  Free(s);
374
375  return(0);
376}
377
378//////////////////////////////////////////////////////////////
379//////////////////////////////////////////////////////////////
380
381//////////////////////////////////////////////////////////////
382//////////////////////////////////////////////////////////////
383
384int XML_Set_Node_Id(xml_node *n, char *id)
385{
386  XML_Make_Node_Id(n,id);
387  strcpy(n->id,id);
388  return(0);
389}
390
391//////////////////////////////////////////////////////////////
392//////////////////////////////////////////////////////////////
393
394
395int XML_Set_Node_Value(xml_node *n, char *val)
396{
397  XML_Make_Node_Value(n,val);
398  strcpy(n->value,val);
399  return(0);
400}
401
402//////////////////////////////////////////////////////////////
403//////////////////////////////////////////////////////////////
404
405xml_node *XML_Search_Node_Generic(char *nd_name, char *attr_name, char *attr_val, int skip, xml_node *node)
406{
407
408  xml_node *match;
409
410  /* if(nd_name) printf("\n. [1] nd_name:%s attr_name:%s attr_val:%s \n", nd_name, attr_name, attr_val); */
411  /* else  printf("\n. attr_name:%s attr_val:%s \n", attr_name, attr_val); */
412 
413  /* printf("\n. name:%s child:%s next:%s ", */
414  /*     node?node->name:"xx", */
415  /*     node->child?node->child->name:"xx", */
416  /*     node->next?node->next->name:"xx"); fflush(NULL); */
417
418
419  match = NULL;
420  if(skip == NO && nd_name && attr_name && attr_val)
421    {
422      if(!strcmp(nd_name, node -> name))
423        {
424          xml_attr *attr = XML_Search_Attribute(node, attr_name);
425          if(attr && !strcmp(attr -> value, attr_val)) match = node;
426        }
427    }
428  else if(skip == NO && !nd_name && attr_name && attr_val)
429    {
430      xml_attr *attr = XML_Search_Attribute(node, attr_name);
431      if(attr && !strcmp(attr -> value, attr_val)) match = node;
432    }
433  else if(skip == NO && nd_name && !attr_name && attr_val)
434    {
435      if(!strcmp(nd_name, node -> name))
436        {
437          do
438            {
439              if(!strcmp(node -> attr -> value, attr_val)) 
440                {
441                  match = node;
442                  break;
443                }
444              node -> attr = node -> attr -> next;
445              if(!node -> attr) break;
446            }
447          while(1);
448        }
449    }
450  else if(skip == NO && nd_name && attr_name && !attr_val)
451    {
452      if(!strcmp(nd_name, node -> name))
453        {
454          do
455            {
456              if(!strcmp(node -> attr -> name, attr_name)) 
457                {
458                  match = node;
459                  break;
460                }
461              node -> attr = node -> attr -> next;
462              if(!node -> attr) break;
463            }
464          while(1);
465        }
466    }
467  else if(skip == NO && nd_name && !attr_name && !attr_val)
468    {
469      if(!strcmp(nd_name, node -> name)) match = node;
470    }
471  else if(skip == NO && !nd_name && attr_name && !attr_val)
472    {
473      xml_attr *attr = XML_Search_Attribute(node, attr_name);
474      if(attr) match = node;
475    }
476  else if(skip == NO && !nd_name && !attr_name && attr_val)
477    {
478      do
479        {
480          if(!strcmp(node -> attr -> value, attr_val)) 
481            {
482              match = node;
483              break;
484            }
485          node -> attr = node -> attr -> next;
486          if(!node -> attr) break;
487        }
488      while(1);
489    }
490
491  // If node has a child, node = child, else if node has next, node = next, else if node
492  // has parent, node = parent->next else node = NULL
493
494  if(match) return(match);
495  if(node -> child)
496    {
497      match = XML_Search_Node_Generic(nd_name, attr_name, attr_val, NO, node -> child);
498    }
499  if(!match && node -> next)
500    {
501      match = XML_Search_Node_Generic(nd_name, attr_name, attr_val, NO, node -> next);
502    }
503  if(match == NULL && node -> parent)
504    {
505      if(node -> parent == NULL) // Reached the root
506        {
507          PhyML_Printf("\n== Could not find a node with name '%s'.", attr_name);
508          Exit("\n");
509        }
510      return NULL;
511    }
512  return match;
513}
514
515//////////////////////////////////////////////////////////////
516//////////////////////////////////////////////////////////////
517
518xml_node *XML_Search_Node_Name(char *name, int skip, xml_node *node)
519{
520
521  xml_node *match;
522 
523  /* printf("\n. name:%s child:%s next:%s ", */
524  /*     node?node->name:"xx", */
525  /*     node->child?node->child->name:"xx", */
526  /*     node->next?node->next->name:"xx"); fflush(NULL); */
527
528
529  match = NULL;
530  if(skip == NO && !strcmp(node->name,name)) match = node;
531  else
532    {
533      // If node has a child, node = child, else if node has next, node = next, else if node
534      // has parent, node = parent->next else node = NULL
535      if(node->child)
536        {
537          match = XML_Search_Node_Name(name,NO,node->child);
538        }
539      if(match == NULL && node->next)
540        {
541          match = XML_Search_Node_Name(name,NO,node->next);
542        }
543      if(match == NULL && node->parent)
544        {
545          if(node->parent == NULL) // Reached the root
546            {
547              PhyML_Printf("\n== Could not find a node with name '%s'.",name);
548              Exit("\n");
549            }
550          return NULL;
551        }
552    }
553  return match;
554}
555
556//////////////////////////////////////////////////////////////
557//////////////////////////////////////////////////////////////
558
559xml_node *XML_Search_Node_ID(char *id, int skip, xml_node *node)
560{
561  xml_node *match;
562 
563  if(!node)
564    {
565      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
566      Exit("\n");         
567    }
568     
569
570  match = NULL;
571  if(skip == NO && node->id && !strcmp(node->id,id)) match = node;
572  else
573    {
574      // If node has a child, node = child, else if node has next, node = next, else if node
575      // has parent, node = parent->next else node = NULL
576      if(node->child)
577        {
578          match = XML_Search_Node_ID(id,NO,node->child);
579        }
580      if(match == NULL && node->next)
581        {
582          match = XML_Search_Node_ID(id,NO,node->next);
583        }
584      if(match == NULL && node->parent)
585        {
586          if(node->parent == NULL) // Reached the root
587            {
588              PhyML_Printf("\n== Could not find a node with id '%s'.",id);
589              Exit("\n");
590            }
591         
592          return NULL;
593        }
594    }
595  return match;
596}
597
598//////////////////////////////////////////////////////////////
599//////////////////////////////////////////////////////////////
600
601xml_node *XML_Search_Node_Attribute_Value(char *attr_name, char *value, int skip, xml_node *node)
602{
603  xml_node *match;
604
605 
606  if(!node)
607    {
608      PhyML_Printf("\n== node: %p attr: %p",node,node?node->attr:NULL);
609      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
610      Exit("\n");         
611    }
612 
613  match = NULL;
614
615  if(skip) 
616    {
617      match = XML_Search_Node_Attribute_Value(attr_name, value, NO, node->child);
618      return match;
619    }
620
621  if(skip == NO && node->attr)
622    {
623      xml_attr *attr;
624
625      attr = node->attr;
626      do
627        {
628          if(!strcmp(attr->name,attr_name) && 
629             !strcmp(attr->value,value)) 
630            {
631              match = node;
632              break;
633            }
634          attr = attr->next;
635          if(!attr) break;
636        }
637      while(1);
638    }
639
640  if(match) return(match);
641
642  if(node->child)
643    {
644      match = XML_Search_Node_Attribute_Value(attr_name,value,NO,node->child);
645      return match;
646    }
647  if(node->next && !match)
648    {
649      match = XML_Search_Node_Attribute_Value(attr_name,value,NO,node->next);
650      return match;
651    }
652  return NULL;
653}
654
655//////////////////////////////////////////////////////////////
656//////////////////////////////////////////////////////////////
657
658
659//////////////////////////////////////////////////////////////
660//////////////////////////////////////////////////////////////
661
662char *XML_Get_Attribute_Value(xml_node *node, char *attr_name)
663{
664  xml_attr *attr;
665 
666  attr = node->attr;
667
668  while(attr && strcmp(attr->name,attr_name))
669    {
670      attr = attr->next;
671     
672      /* if(attr == NULL) */
673      /*        { */
674      /*          PhyML_Printf("\n== Could not find an attribute with name '%s' in node with name '%s'.",id,node->name); */
675      /*          Exit("\n"); */
676      /*        } */
677    }
678
679  return(attr?attr->value:NULL);
680}
681
682//////////////////////////////////////////////////////////////
683//////////////////////////////////////////////////////////////
684
685int XML_Validate_Attr_Int(char *target, int num, ...)
686{
687  va_list args;                     
688  int i;
689  char *s,*sc_s;
690  char *sc_target;
691 
692  sc_target = To_Lower_String(target);
693
694  va_start(args,num);           
695  For(i,num)
696    {
697      s = va_arg(args, char *); 
698      sc_s = To_Lower_String(s);
699      if(!strcmp(sc_s,sc_target)) 
700        {
701          Free(sc_s);
702          break;
703        }
704      Free(sc_s);
705    }
706  va_end(args);
707
708  if(i == num) 
709    {
710      i = -1;
711      PhyML_Printf("\n== Attribute value '%s' is not valid",target);
712      Exit("\n");
713    }
714
715  Free(sc_target);
716
717  return(i);
718}
719
720//////////////////////////////////////////////////////////////
721//////////////////////////////////////////////////////////////
722
723void XML_Check_Siterates_Node(xml_node *parent)
724{
725  xml_node *n;
726  int n_weights_nodes;
727  char *rate_value = NULL;
728  phydbl buff;
729  int n_zeros;
730  char *endptr;
731
732  if(!parent)
733    {
734      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
735      Exit("\n");         
736    }
737
738  if(strcmp(parent->name,"siterates"))
739    {
740      PhyML_Printf("\n== Node name '%s' should be 'siterates'",parent->name);
741      Exit("\n");
742    }
743 
744  // Check that only one 'weights' node is present
745  n_weights_nodes = 0;
746  n = parent->child;
747  do
748    {
749      if(!strcmp(n->name,"weights")) n_weights_nodes++;
750      if(n_weights_nodes > 1)
751        {
752          PhyML_Printf("\n== Only one distribution is authorized for 'siterates' nodes.");
753          Exit("\n");
754        }
755      n = n->next;
756      if(!n) break;
757    }
758  while(1);
759
760  // Check that one rate value is set to zero if gamma+inv model is used
761  n = XML_Search_Node_Attribute_Value("family","gamma+inv",YES,parent);
762  if(!n) return;
763  else
764    {
765      n_zeros = 0;
766      n = parent->child;
767      do
768        {
769          if(!strcmp(n->name,"instance"))
770            {
771              rate_value = NULL;
772              rate_value = XML_Get_Attribute_Value(n,"init.value"); 
773
774              if(rate_value)
775                {
776                  errno = 0;
777                  buff = strtod(rate_value,&endptr);
778                 
779                  if(rate_value == endptr || errno == ERANGE)
780                    {
781                      PhyML_Printf("\n== value: %s",rate_value);
782                      PhyML_Printf("\n== Error in reading attribute 'init.value' in node 'instance'.");
783                      Exit("\n");
784                    }
785                 
786                  if(buff < 1.E-20) n_zeros++;           
787                }
788            }
789          n = n->next;
790          if(!n) break;
791        }
792      while(1);
793     
794      if(n_zeros != 1)
795        {
796          PhyML_Printf("\n== # of zero-rates: %d",n_zeros);
797          PhyML_Printf("\n== Exactly one rate value has to be set to zero when using the 'gamma+inv' model.");
798          PhyML_Printf("\n== Component id: %s",parent->id);
799          Exit("\n");
800        }
801    }
802}
803
804//////////////////////////////////////////////////////////////
805//////////////////////////////////////////////////////////////
806
807int XML_Get_Number_Of_Classes_Siterates(xml_node *parent)
808{
809  xml_node *n;
810  int n_classes;
811
812  if(!parent)
813    {
814      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
815      Exit("\n");         
816    }
817
818  n_classes = 0;
819  n = parent->child;
820  do
821    {
822      if(!strcmp(n->name,"instance")) n_classes++;       
823      n = n->next;
824      if(!n) break;
825    }
826  while(1);
827 
828  n = NULL;
829  n = XML_Search_Node_Attribute_Value("family","gamma+inv",YES,parent);
830
831  if(!n) return n_classes;
832  else return n_classes-1;
833}
834
835//////////////////////////////////////////////////////////////
836
837int XML_Siterates_Has_Invariants(xml_node *parent)
838{
839  xml_node *n;
840
841  if(!parent)
842    {
843      PhyML_Printf("\n== Err in file %s at line %d\n",__FILE__,__LINE__);
844      Exit("\n");         
845    }
846     
847  n = NULL;
848  n = XML_Search_Node_Attribute_Value("family","gamma+inv",YES,parent);
849
850  if(!n) return NO;
851  else return YES;
852}
853
854//////////////////////////////////////////////////////////////
855
856void XML_Count_Number_Of_Node_With_ID(char *id, int *count, xml_node *n)
857{
858  if(!id) return;
859  if(n->id && !strcmp(n->id,id)) (*count)++;
860 
861  if(n->child) XML_Count_Number_Of_Node_With_ID(id,count,n->child);
862  if(n->next)  XML_Count_Number_Of_Node_With_ID(id,count,n->next);
863   
864}
865
866//////////////////////////////////////////////////////////////
867
868void XML_Count_Number_Of_Node_With_Name(char *name, int *count, xml_node *n)
869{
870  if(!name) return;
871  if(n->name && !strcmp(n->name,name)) (*count)++;
872 
873  if(n->child) XML_Count_Number_Of_Node_With_Name(name,count,n->child);
874  if(n->next)  XML_Count_Number_Of_Node_With_Name(name,count,n->next);
875   
876}
877
878//////////////////////////////////////////////////////////////
879
880void XML_Check_Duplicate_ID(xml_node *n)
881{
882  int count;
883 
884  count = 0;
885  XML_Count_Number_Of_Node_With_ID(n->id,&count,n);
886 
887  if(count > 1)
888    {
889      PhyML_Printf("\n== Node ID'%s' was found in more than once.",n->id);
890      PhyML_Printf("\n== Each ID must be unique. Please amend your XML");
891      PhyML_Printf("\n== file accordingly.");
892      Exit("\n");
893    }
894
895  if(n->child) XML_Check_Duplicate_ID(n->child);
896  if(n->next) XML_Check_Duplicate_ID(n->next);
897}
898
899//////////////////////////////////////////////////////////////
900
901xml_node *XML_Copy_XML_Graph(xml_node *root)
902{
903  xml_node *cpy_root;
904
905  cpy_root = XML_Make_Node(root->name);
906  XML_Copy_XML_Node(cpy_root,root);
907
908  return(cpy_root);
909}
910
911//////////////////////////////////////////////////////////////
912
913void XML_Copy_XML_Node(xml_node *cpy_root, xml_node *root)
914{
915  xml_attr *attr,*cpy_attr;
916 
917  strcpy(cpy_root->name,root->name);
918
919  XML_Make_Node_Id(cpy_root,root->id); 
920  if(root->id) strcpy(cpy_root->id,root->id);
921
922  XML_Make_Node_Value(cpy_root,root->value);
923  if(root->value) strcpy(cpy_root->value,root->value);
924
925  cpy_root->n_attr = root->n_attr;
926
927  if(root->attr)
928    {
929      cpy_root->attr = XML_Make_Attribute(NULL,root->attr->name,root->attr->value);
930      XML_Init_Attribute(cpy_root->attr);
931      attr           = root->attr;
932      cpy_attr       = cpy_root->attr;
933      while(attr->next)
934        {
935          fflush(NULL);
936          cpy_attr->next = XML_Make_Attribute(cpy_attr,attr->next->name,attr->next->value);
937          XML_Init_Attribute(cpy_attr->next);
938          attr           = attr->next;
939          cpy_attr       = cpy_attr->next;
940        }
941    }
942   
943  if(root->child)
944    {
945      cpy_root->child = XML_Make_Node(root->child->name);
946      cpy_root->child->parent = cpy_root;
947      XML_Copy_XML_Node(cpy_root->child,root->child);
948    }
949
950  if(root->next)
951    {
952      cpy_root->next = XML_Make_Node(root->next->name);
953      cpy_root->next->prev = cpy_root;
954      XML_Copy_XML_Node(cpy_root->next,root->next);
955    }
956}
957
958//////////////////////////////////////////////////////////////
959
960void XML_Write_XML_Graph(FILE *fp, xml_node *root)
961{
962  int indent;
963  indent = 0;
964  XML_Write_XML_Node(fp,&indent,root);
965}
966
967//////////////////////////////////////////////////////////////
968
969void XML_Write_XML_Node(FILE *fp, int *indent, xml_node *root)
970{
971  xml_node *n;
972  xml_attr *attr;
973  char *s;
974  int i;
975
976  s = (char *)mCalloc((*indent)+1,sizeof(char));
977  For(i,(*indent)) s[i]='\t';
978  s[i]='\0';
979
980
981  PhyML_Fprintf(fp,"\n%s",s);
982 
983  n = root;
984 
985  PhyML_Fprintf(fp,"<%s",n->name);
986
987  attr = n->attr; 
988  while(attr)
989    {
990      PhyML_Fprintf(fp," %s=\"%s\"",attr->name,attr->value);
991      fflush(NULL);
992      attr = attr->next;
993    }
994
995 
996  if(n->child)
997    {
998      (*indent)++;
999      PhyML_Fprintf(fp,">");
1000      XML_Write_XML_Node(fp,indent,n->child);
1001      PhyML_Fprintf(fp,"\n%s</%s>\n",s,n->name);
1002      (*indent)--;
1003    }
1004  else
1005    {
1006      PhyML_Fprintf(fp,"/>");
1007    }
1008
1009  if(n->next)
1010    XML_Write_XML_Node(fp,indent,n->next);
1011 
1012
1013  Free(s);
1014}
1015
1016//////////////////////////////////////////////////////////////
1017
1018void Check_Mandatory_XML_Node(xml_node *root, char *name)
1019{
1020  if(!XML_Search_Node_Name(name,NO,root))
1021    {
1022      PhyML_Printf("\n== Could not find mandatory XML node with name '%s'.",name);
1023      PhyML_Printf("\n== Please amend your XML file.");
1024      Exit("\n");
1025    }
1026}
1027
1028
1029
1030
1031//////////////////////////////////////////////////////////////
1032//////////////////////////////////////////////////////////////
1033//////////////////////////////////////////////////////////////
1034//////////////////////////////////////////////////////////////
1035//////////////////////////////////////////////////////////////
1036//////////////////////////////////////////////////////////////
1037//////////////////////////////////////////////////////////////
1038//////////////////////////////////////////////////////////////
1039//////////////////////////////////////////////////////////////
1040//////////////////////////////////////////////////////////////
1041//////////////////////////////////////////////////////////////
1042//////////////////////////////////////////////////////////////
1043//////////////////////////////////////////////////////////////
1044//////////////////////////////////////////////////////////////
1045//////////////////////////////////////////////////////////////
1046//////////////////////////////////////////////////////////////
1047//////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.