Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: minimal xml parser?

From: "cr88192" <cr88192@------.-------.--->
To: NULL
Date: 11/1/2004 12:17:00 PM
"Mike" <mikee@m...> wrote in message 
news:10nqqmnq3n1ln8d@c......
> Does anyone know of a minimal/mini/tiny/small xml parser
> in c? I'm looking for something small that accepts a stream
> or string, builds a c structure, and then returns an opaque
> pointer to that structure. There should then be a function
> to search that structure given the pointer, tag, and an
> optional attribute. I'm looking initially at only text data,
> no numbers, though eventuall there will be some binary
> data (CDATA?).
>
oh well, this thread is new enough that I think I will add my comment.

if motivated, maybe my parser could be made to work in your case.
kalloc/kfree are for my allocator.
kralloc is a rotating allocator (allocates from a large circular buffer), 
and thus does not need freeing.

ObjType_New can be replaced by kalloc (or malloc if needed).

be warned if replacing kalloc or such with malloc in that it will be 
necessary to zero memory returned by malloc (not necissarily done by malloc 
by default).

I ommited, eg, the printer here though...

part of the header:
----
#define TOKEN_NULL 0
#define TOKEN_SPECIAL 1
#define TOKEN_STRING 2
#define TOKEN_SYMBOL 3

typedef struct NetParse_Attr_s NetParse_Attr;
typedef struct NetParse_Node_s NetParse_Node;

struct NetParse_Attr_s {
NetParse_Attr *next;
char *ns;
char *key;
char *value;
};

struct NetParse_Node_s {
NetParse_Node *next;
char *ns;
char *key;
char *text;
NetParse_Attr *attr;
NetParse_Node *first;
};


dump of part of my parser:
----
/*--
Cat pdlib;Parse;XML
Form
 char *NetParse_XML_EatWhite(char *s);
Description
 Skips over whitespace.
Status Internal
--*/
char *NetParse_XML_EatWhite(char *s)
{
 int i, r;

 i=0;
 while(*s && *s<=' ')
 {
  if(*s=='\n')
  {
   line++;
   *s=' ';
  }
  i=1;
  s++;
 }

 if(i)s=NetParse_XML_EatWhite(s);

 return(s);
}

/*--
Cat pdlib;Parse;XML
Form
 int NetParse_XML_SpecialP(char *s);
Description
 Returns a nonzero value if *s is special.
Status Internal
--*/
int NetParse_XML_SpecialP(char *s)
{
 switch(*s)
 {
 case '<':
  return(1);
  break;
 case '>':
  return(1);
  break;
 case '/':
  return(1);
  break;
 case '=':
  return(1);
  break;
 case '?':
  return(1);
  break;
 case ':':
  return(1);
  break;
 default:
  return(0);
  break;
 }
 return(0);
}

/*--
Cat pdlib;Parse;XML
Form
 int NetParse_XML_ContSpecialP(char *s);
Description
 Returns nonzero if this will get the parsers attention when reading as 
text.
 This includes '<' and '&'.
Status Internal
--*/
int NetParse_XML_ContSpecialP(char *s)
{
 switch(*s)
 {
 case '<':
  return(1);
  break;
 case '&':
  return(1);
  break;
 default:
  return(0);
  break;
 }
 return(0);
}

/*--
Cat pdlib;Parse;XML
Form
 char *NetParse_XML_Token(char *s, char *b, int *t);
Description
 Reads a token from the XML stream.
 This includes:
  Individual symbols;
  Globs of text/tags;
  Strings.
 b is the buffer.
 t is an integer to hold the token type
  TOKEN_NULL, a null terminator was reached;
  TOKEN_SPECIAL, a special character.
  TOKEN_STRING, a quoted string literal (escapes processed).
  TOKEN_SYMBOL, an unquoted bit of text (eg: a tag).
 Returns the next character after the token.
Status Internal
--*/
char *NetParse_XML_Token(char *s, char *b, int *t)
{
 char *ob, *is, *t2;
 char *buf;
 int i;

 is=s;
 if(!b)b=kralloc(256);
 ob=b;
 *b=0;

 if(t)*t=0;

 buf=kralloc(16);

 s=NetParse_XML_EatWhite(s);
 if(!*s)
 {
  *t=TOKEN_NULL;
  return(s);
 }

 if(NetParse_XML_SpecialP(s))
 {
  if(t)*t=TOKEN_SPECIAL;

  *b++=*s++;
  *b=0;
 }else if((*s=='"') || (*s=='\'')) /* quoted string */
 {
  if(t)*t=TOKEN_STRING;
  s++;
  while(*s && (*s!='"') && (*s!='\''))
  {
   if(*s=='&')
   {
    s++;
    t2=buf;
    while(*s && (*s!=';'))*t2++=*s++;
    if(!*s)return(NULL);
    *t2++=0;
    s++;

    if(buf[0]=='#')
    {
     if(buf[1]=='x')
     {
      t=buf+2;
      i=0;
      while(*t)
      {
       i<<=4;
       if((*t>='0') && (*t<='9'))
        i+=*t-'0';
       if((*t>='A') && (*t<='F'))
        i+=*t-'A'+10;
       if((*t>='a') && (*t<='f'))
        i+=*t-'a'+10;
       t++;
      }
      *b++=i;
     }else *b++=atoi(buf+1);
    }
    if(!strcmp(buf, "amp"))*b++='&';
    if(!strcmp(buf, "lt"))*b++='<';
    if(!strcmp(buf, "gt"))*b++='>';
    if(!strcmp(buf, "quot"))*b++='"';
    if(!strcmp(buf, "apos"))*b++='\'';
   }else *b++=*s++;
  }
  if(!*s)
  {
   *t=TOKEN_NULL;
   return(is);
  }
  *b++=0;
  s++;
 }else
 {
  if(t)*t=TOKEN_SYMBOL;

  while(*s && (*s>' ') && !NetParse_XML_SpecialP(s) &&
   ((b-ob)<254))
   *b++=*s++;
  *b++=0;

  if(!*s)
  {
   *t=TOKEN_NULL;
   return(is);
  }
 }
 return(s);
}

/*--
Cat pdlib;Parse;XML
Form
 char *NetParse_XML_ParseText(char *s, char *b);
Description
 Parse a glob of text from the stream.
 Handles escapes and such.
Status Internal
--*/
char *NetParse_XML_ParseText(char *s, char *b)
{
 char *ob, *t;
 char buf[16];
 int i, gws, rws;

 if(!b)b=kralloc(4096);
 ob=b;
 *b=0;

 s=NetParse_XML_EatWhite(s);
 if(!*s)return(NULL);

 gws=0;
 rws=0;
 while(1)
 {
  while(*s && !NetParse_XML_ContSpecialP(s))
  {
   if((*s=='\r') || (*s=='\n'))
   {
    s=NetParse_XML_EatWhite(s);
    if(!rws)
    {
     *b++=' ';
     gws++;
    }
    continue;
   }
   gws=0;
   if(*s<=' ')rws++;
    else rws=0;
   *b++=*s++;
  }
  if(!*s)return(NULL);

  if(*s=='&')
  {
   s++;
   t=buf;
   while(*s && (*s!=';'))*t++=*s++;
   if(!*s)return(NULL);
   *t++=0;
   s++;

   if(buf[0]=='#')
   {
    if(buf[1]=='x')
    {
     t=buf+2;
     i=0;
     while(*t)
     {
      i<<=4;
      if((*t>='0') && (*t<='9'))
       i+=*t-'0';
      if((*t>='A') && (*t<='F'))
       i+=*t-'A'+10;
      if((*t>='a') && (*t<='f'))
       i+=*t-'a'+10;
      t++;
     }
     gws=0;
     if(i<=' ')rws++;
      else rws=0;
     *b++=i;
    }else
    {
     i=atoi(buf+1);
     gws=0;
     if(i<=' ')rws++;
      else rws=0;
     *b++=i;
    }
    continue;
   }
   rws=0;
   gws=0;

   if(!strcmp(buf, "amp"))*b++='&';
   if(!strcmp(buf, "lt"))*b++='<';
   if(!strcmp(buf, "gt"))*b++='>';
   if(!strcmp(buf, "apos"))*b++='\'';
   if(!strcmp(buf, "quot"))*b++='"';
  }else break;
 }
 b-=gws;
 *b++=0;

 return(s);
}

/*--
Cat pdlib;Parse;XML
Form
 NetParse_Attr *NetParse_XML_ParseOpts(char **s);
Description
 Parse the list of attributes within a tag.
Status Internal
--*/
NetParse_Attr *NetParse_XML_ParseOpts(char **s)
{
// char ns[32];
// char var[32];
// char eq[16];
// char val[256];
 char *is, *ns, *var, *eq, *val;
 int ty;
 NetParse_Attr *lst, *end, *tmp;

 ns=kralloc(256);
 var=kralloc(256);
 eq=kralloc(256);
 val=kralloc(4096);

 lst=NULL;
 end=NULL;

 is=*s;
 while(1)
 {
  NetParse_XML_Token(*s, var, &ty);
  if(ty==TOKEN_NULL)
  {
   kprint("m1\n");
   *s=NULL;
   return(NULL);
  }

  if((var[0]=='>') && (ty==TOKEN_SPECIAL))
   break;
  if((var[0]=='/') && (ty==TOKEN_SPECIAL))
   break;
  if((var[0]=='?') && (ty==TOKEN_SPECIAL))
   break;
  if(ty==TOKEN_NULL)
  {
   kprint("m2\n");
   *s=NULL;
   return(NULL);
  }
  if(ty!=TOKEN_SYMBOL)
  {
   kprint("parse error (inv attribute).\n");
   return(NULL);
  }

  *s=NetParse_XML_Token(*s, var, &ty);
  if(ty==TOKEN_NULL)
  {
   kprint("m3\n");
   *s=NULL;
   return(NULL);
  }
  *s=NetParse_XML_Token(*s, eq, &ty);
  if(ty==TOKEN_NULL)
  {
   kprint("m4\n");
   *s=NULL;
   return(NULL);
  }

  if((ty==TOKEN_SPECIAL) && (eq[0]==':'))
  {
   strcpy(ns, var);

   *s=NetParse_XML_Token(*s, var, &ty);
   if(ty==TOKEN_NULL)
   {
    kprint("m41\n");
    *s=NULL;
    return(NULL);
   }
   *s=NetParse_XML_Token(*s, eq, &ty);
   if(ty==TOKEN_NULL)
   {
    kprint("m42\n");
    *s=NULL;
    return(NULL);
   }
  }else ns[0]=0;

  if((ty!=TOKEN_SPECIAL) || (eq[0]!='='))
  {
   kprint("parse error (attr equal).\n");
   return(NULL);
  }

  *s=NetParse_XML_Token(*s, val, &ty);
  if(ty==TOKEN_NULL)
  {
   kprint("m5\n");
   *s=NULL;
   return(NULL);
  }

  if(ty!=TOKEN_STRING)
  {
   kprint("parse error (inv attribute arg).\n");
   return(NULL);
  }

//  t=CONS(SYM(var), CONS(STRING(val), MISC_EOL));
//  x=CONS(t, x);
//  tmp=kalloc(sizeof(NetParse_Attr));
  tmp=NetParse_NewAttr();
  tmp->next=NULL;
  if(ns[0])tmp->ns=kstrdup(ns);
  tmp->key=kstrdup(var);
  tmp->value=kstrdup(val);

  if(end)
  {
   end->next=tmp;
   end=tmp;
  }else
  {
   lst=tmp;
   end=tmp;
  }
 }

 return(lst);
}

/*--
Cat pdlib;Parse;XML
Form
 NetParse_Node *NetParse_XML_ParseExpr(char **s);
Description
 Parses an XML expression.
 s is updated to reflect the change.

 NULL is returned on parse error or end-of-stream.
 s is not updated for end of stream conditions, which can be used to 
seperate it from a parse error.
--*/
NetParse_Node *NetParse_XML_ParseExpr(char **s)
{
// char buf[256], buf2[16];
// char key[32], ns[32];
 char *buf, *buf2, *key, *ns;

 int ty, i;
 char *s2, *s3, *s4, *is;

// elem kv, opts, t, x;
 NetParse_Node *tmp, *t, *end;

 is=*s;
 *s=NetParse_XML_EatWhite(*s);
 if(!*(*s))return(NULL);

 buf=kalloc(256);
 buf2=kalloc(256);
 key=kalloc(256);
 ns=kalloc(256);

// strncpy(buf, *s, 5);
// buf[5]=0;
// kprint("parse: %s\n", buf);

 NetParse_XML_Token(*s, buf, &ty);
 if(ty==TOKEN_NULL)
 {
  kfree(buf);
  kfree(buf2);
  kfree(key);
  kfree(ns);
  *s=is;
  return(NULL);
 }
 if((buf[0]=='<') && (ty==TOKEN_SPECIAL))
 {
  *s=NetParse_XML_Token(*s, buf, &ty);
  if(ty==TOKEN_NULL)
  {
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   *s=is;
   return(NULL);
  }
  if(*s[0]=='?')
   *s=*s+1;
  if(*s[0]=='!')
  {
   if(!strncmp(*s, "[CDATA[", 7))
   {
    *s=*s+7;
    s2=kalloc(65536);
    s3=s2;
    s4=*s;
    while(*s4)
    {
     if(!strncmp(s4, "]]>", 3))
     {
      s4+=3;
      break;
     }
     if(!strncmp(s4, "]]&gt;", 6))
     {
      s4+=6;

      *s3++=']';
      *s3++=']';
      *s3++='>';
      continue;
     }
     *s3++=*s4++;
    }
    if(!*s4)
    {
     kfree(s2);

     kfree(buf);
     kfree(buf2);
     kfree(key);
     kfree(ns);
     *s=is;
     return(NULL);
    }

    *s3++=0;
    *s=s4;

    tmp=NetParse_NewNode();
    tmp->next=NULL;
    tmp->key=NULL;
    tmp->text=kstrdup(s2);
    tmp->attr=NULL;
    tmp->first=NULL;

    kfree(s2);

    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    return(tmp);
   }

   s2=*s;
   i=1;
   while(*s2 && i)
   {
    if(*s2=='<')i++;
    if(*s2=='>')i--;
    if(*s2=='[')i++;
    if(*s2==']')i--;
    s2++;
   }

   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   *s=s2;
   return(NetParse_XML_ParseExpr(s));
  }

  *s=NetParse_XML_Token(*s, key, &ty);
  if(ty==TOKEN_NULL)
  {
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   *s=is;
   return(NULL);
  }
  if(ty!=TOKEN_SYMBOL)
  {
   kprint("parse error (inv tag).\n");
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   return(NULL);
  }

  if(**s==':')
  {
   *s=*s+1;
   strcpy(ns, key);
   *s=NetParse_XML_Token(*s, key, &ty);
  }else ns[0]=0;

  if((**s>' ') && (**s!='>') && (**s!='/'))
  {
   kprint("parse error (inv char after tag).\n");
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   return(NULL);
  }
//  kv=SYM(key);
//  opts=NetParse_XML_ParseOpts(s);
//  if(opts==MISC_UNDEFINED)return(t);

//  tmp=kalloc(sizeof(NetParse_Node));
  tmp=NetParse_NewNode();
  tmp->next=NULL;
  if(ns[0])tmp->ns=kstrdup(ns);
  tmp->key=kstrdup(key);
  s3=*s;
  tmp->attr=NetParse_XML_ParseOpts(s);
  if(!*s)
  {
   kprint("attr traunc\n");
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   *s=is;
   return(NULL);
  }
  tmp->first=NULL;

  *s=NetParse_XML_Token(*s, buf, &ty);
  if(ty==TOKEN_NULL)
  {
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   *s=is;
   return(NULL);
  }
  if((buf[0]=='/') && (ty==TOKEN_SPECIAL))
  {
   *s=NetParse_XML_Token(*s, buf, &ty);
   if(ty==TOKEN_NULL)
   {
    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    *s=is;
    return(NULL);
   }
   return(tmp);
  }
  if((buf[0]=='?') && (ty==TOKEN_SPECIAL))
  {
   *s=NetParse_XML_Token(*s, buf, &ty);
   if(ty==TOKEN_NULL)
   {
    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    *s=is;
    return(NULL);
   }
//   x=CONS(kv, CONS(opts, MISC_EOL));
//   x=CONS(SYM("?"), x);
   strcpy(buf, "?");
   strcat(buf, tmp->key);
   kfree(tmp->key);
   tmp->key=kstrdup(buf);

   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   return(tmp);
  }
  if(buf[0]!='>')
  {
   kprint("parse error (expected close '>').\n");
   kfree(buf);
   kfree(buf2);
   kfree(key);
   kfree(ns);
   return(NULL);
  }

  end=NULL;
//  x=MISC_EOL;
  while(1)
  {
   s2=*s;
   s2=NetParse_XML_Token(s2, buf, &ty);
   if(ty==TOKEN_NULL)
   {
    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    *s=is;
    return(NULL);
   }
   s2=NetParse_XML_Token(s2, buf2, &ty);
   if(ty==TOKEN_NULL)
   {
    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    *s=is;
    return(NULL);
   }

   if(buf[0]=='<' && buf2[0]=='/')
   {
    s2=NetParse_XML_Token(s2, buf, &ty);
    if(ty==TOKEN_NULL)
    {
     kfree(buf);
     kfree(buf2);
     kfree(key);
     kfree(ns);
     *s=is;
     return(NULL);
    }
    s2=NetParse_XML_Token(s2, buf, &ty);
    if(ty==TOKEN_NULL)
    {
     kfree(buf);
     kfree(buf2);
     kfree(key);
     kfree(ns);
     *s=is;
     return(NULL);
    }
    *s=s2;
    break;
   }
   s3=*s;
   t=NetParse_XML_ParseExpr(s);
   if(*s==s3)
   {
    kfree(buf);
    kfree(buf2);
    kfree(key);
    kfree(ns);
    *s=is;
    return(NULL);
   }

   if(!t)return(t);
//   x=CONS(t, x);
   if(end)
   {
    end->next=t;
    end=t;
   }else
   {
    tmp->first=t;
    end=t;
   }
  }
  kfree(buf);
  kfree(buf2);
  kfree(key);
  kfree(ns);
  return(tmp);
 }

 s2=kalloc(65536);
 *s=NetParse_XML_ParseText(*s, s2);
 if(!*s)
 {
  kfree(buf);
  kfree(buf2);
  kfree(key);
  kfree(ns);
  *s=is;
  return(NULL);
 }

// tmp=kalloc(sizeof(NetParse_Node));
 tmp=NetParse_NewNode();
 tmp->next=NULL;
 tmp->key=NULL;
 tmp->text=kstrdup(s2);
 tmp->attr=NULL;
 tmp->first=NULL;

 kfree(s2);

 kfree(buf);
 kfree(buf2);
 kfree(key);
 kfree(ns);
 return(tmp);
}

/*--
Cat pdlib;Parse;XML
Form
 NetParse_Node *NetParse_XML_LoadFile(char *name);
Description
 loads XML from a file.
 returns NULL on failure.
--*/
NetParse_Node *NetParse_XML_LoadFile(char *name)
{
 VFILE *fd;
 char *buf, *s;
 NetParse_Node *n;

 fd=vffopen(name, "rb");
 if(!fd)return(NULL);

 buf=vf_bufferin(fd);
 if(!buf)return(NULL);

 s=buf;
 while(*s)
 {
  n=NetParse_XML_ParseExpr(&s);
  if(!n)break;
  if(n->key[0]=='?')continue;
  return(n);
 }
 return(NULL);
}

and part of the crap for dealing with parse trees:
----
/*--
Cat pdlib;Parse
Form
 int NetParse_Init();
Description
 Init function for NetParse, called implicitly by node/attr creation.
--*/
int NetParse_Init()
{
 static int init=0;

 if(init)return(1);
 init=1;

 ObjType_NewType("netparse_attr_t", "*struct;string;string;");
 ObjType_NewType("netparse_node_t",
  "*struct;string;string;*struct;*struct;");
 return(0);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Attr *NetParse_NewAttr();
Description
 Creates a new attribute.
--*/
NetParse_Attr *NetParse_NewAttr()
{
 NetParse_Attr *tmp;

 NetParse_Init();

// tmp=kalloc(sizeof(NetParse_Attr));
 tmp=ObjType_New("netparse_attr_t", sizeof(NetParse_Attr));
 tmp->next=NULL;
 tmp->key=NULL;
 tmp->value=NULL;

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Attr *NetParse_AddAttr(NetParse_Node *node, char *key, char 
*value);
Description
 Adds an attribute to a node (or sets the attribute if present).
--*/
NetParse_Attr *NetParse_AddAttr(NetParse_Node *node, char *key, char *value)
{
 NetParse_Attr *tmp, *cur;

 cur=node->attr;
 while(cur)
 {
  if(!strcmp(cur->key, key))
  {
   if(cur->value)kfree(cur->value);
   cur->value=kstrdup(value);
   return(cur);
  }
  cur=cur->next;
 }

// tmp=kalloc(sizeof(NetParse_Attr));
 tmp=NetParse_NewAttr();
 tmp->next=NULL;
 tmp->key=kstrdup(key);
 tmp->value=kstrdup(value);

 if(!node->attr)
 {
  node->attr=tmp;
  return(tmp);
 }
 cur=node->attr;
 while(cur->next)cur=cur->next;
 cur->next=tmp;

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Attr *NetParse_AddAttrList(NetParse_Attr *lst, char *key, char 
*value);
Description
 Adds an attribute to a list of attributes (or assigns the attribure  if allready present).
 Returns the start of the list, or the new attribute if lst is NULL.
--*/
NetParse_Attr *NetParse_AddAttrList(NetParse_Attr *lst, char *key, char 
*value)
{
 NetParse_Attr *tmp, *cur;

 cur=lst;
 while(cur)
 {
  if(!strcmp(cur->key, key))
  {
   if(cur->value)kfree(cur->value);
   cur->value=kstrdup(value);
   return(lst);
  }
  cur=cur->next;
 }

// tmp=kalloc(sizeof(NetParse_Attr));
 tmp=NetParse_NewAttr();
 tmp->next=NULL;
 tmp->key=kstrdup(key);
 tmp->value=kstrdup(value);

 if(!lst)return(tmp);

 cur=lst;
 while(cur->next)cur=cur->next;
 cur->next=tmp;

 return(lst);
}

/*--
Cat pdlib;Parse
Form
 char *NetParse_GetNodeAttr(NetParse_Node *node, char *key);
Description
 Gets an attribute associated with a node.
 Returns NULL if not found.
--*/
char *NetParse_GetNodeAttr(NetParse_Node *node, char *key)
{
 NetParse_Attr *cur;

 cur=node->attr;
 while(cur)
 {
  if(!strcmp(cur->key, key))return(cur->value);
  cur=cur->next;
 }
 return(NULL);
}

/*--
Cat pdlib;Parse
Form
 int NetParse_GetNodeAttrIsP(NetParse_Node *node, char *key, char *value);
Description
 Check if a given node has a certain attribute as a certain value.
--*/
int NetParse_GetNodeAttrIsP(NetParse_Node *node, char *key, char *value)
{
 NetParse_Attr *cur;

 cur=node->attr;
 while(cur)
 {
  if(!strcmp(cur->key, key))
  {
   if(!strcmp(cur->value, value))
    return(1);
    else return(0);
  }
  cur=cur->next;
 }
 return(0);
}

/*--
Cat pdlib;Parse
Form
 char *NetParse_GetAttrList(NetParse_Attr *lst, char *key);
Description
 Gets an attribute in a list.
 Returns NULL if not found.
--*/
char *NetParse_GetAttrList(NetParse_Attr *lst, char *key)
{
 NetParse_Attr *cur;

 cur=lst;
 while(cur)
 {
  if(!strcmp(cur->key, key))return(cur->value);
  cur=cur->next;
 }
 return(NULL);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_NewNode();
Description
 Creates a new node.
--*/
NetParse_Node *NetParse_NewNode()
{
 NetParse_Node *tmp;

 NetParse_Init();

// tmp=kalloc(sizeof(NetParse_Node));
 tmp=ObjType_New("netparse_node_t", sizeof(NetParse_Node));
 tmp->next=NULL;
 tmp->key=NULL;
 tmp->text=NULL;
 tmp->attr=NULL;
 tmp->first=NULL;

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_AddNodeEnd(NetParse_Node *first, NetParse_Node 
*node);
Description
 Adds a new node at the end of a list of nodes.
--*/
NetParse_Node *NetParse_AddNodeEnd(NetParse_Node *first, NetParse_Node 
*node)
{
 NetParse_Node *cur;

 if(!first)return(node);

 cur=first;
 while(cur->next)cur=cur->next;
 cur->next=node;

 return(first);
}

/*--
Cat pdlib;Parse
Form
 int NetParse_AddChildNode(NetParse_Node *parent, NetParse_Node *node);
Description
 Add a new child node to a parent.
--*/
int NetParse_AddChildNode(NetParse_Node *parent,
 NetParse_Node *node)
{
 NetParse_Node *cur;

 if(!parent->first)
 {
  parent->first=node;
  return(0);
 }

 cur=parent->first;
 while(cur->next)cur=cur->next;
 cur->next=node;

 return(0);
}

/*--
Cat pdlib;Parse
Form
 int NetParse_FreeAttr(NetParse_Attr *attr);
Description
 Frees an attribute.
 Also frees any following attributes.
--*/
int NetParse_FreeAttr(NetParse_Attr *attr)
{
 if(attr->next)NetParse_FreeAttr(attr->next);
 if(attr->key)kfree(attr->key);
 if(attr->value)kfree(attr->value);
 kfree(attr);

 return(0);
}

/*--
Cat pdlib;Parse
Form
 int NetParse_FreeNode(NetParse_Node *node);
Description
 Frees a node and any associated attributes.
 Also frees any child nodes.
--*/
int NetParse_FreeNode(NetParse_Node *node)
{
 NetParse_Node *cur, *next;

 if(node->key)kfree(node->key);
 if(node->text)kfree(node->text);
 if(node->attr)NetParse_FreeAttr(node->attr);

 cur=node->first;
 while(cur)
 {
  next=cur->next;

  if(cur->key)kfree(cur->key);
  if(cur->text)kfree(cur->text);
  if(cur->attr)NetParse_FreeAttr(cur->attr);
  if(cur->first)NetParse_FreeNode(cur->first);
  kfree(cur);

  cur=next;
 }
 kfree(node);

 return(0);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Attr *NetParse_CopyAttr(NetParse_Attr *attr);
Description
 Copies an attribute along with any following attributes.
--*/
NetParse_Attr *NetParse_CopyAttr(NetParse_Attr *attr)
{
 NetParse_Attr *tmp;

 tmp=NetParse_NewAttr();

 if(attr->next)
  tmp->next=NetParse_CopyAttr(attr->next);
 if(attr->key)
  tmp->key=kstrdup(attr->key);
 if(attr->value)
  tmp->value=kstrdup(attr->value);

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_CopyNode(NetParse_Node *node);
Description
 Makes a copy of a node tree, copies any attributes or children.
--*/
NetParse_Node *NetParse_CopyNode(NetParse_Node *node)
{
 NetParse_Node *cur;
 NetParse_Node *tmp, *lst, *end, *t2;

 tmp=NetParse_NewNode();
 if(node->key)
  tmp->key=kstrdup(node->key);
 if(node->text)
  tmp->text=kstrdup(node->text);
 if(node->attr)
  tmp->attr=NetParse_CopyAttr(node->attr);

 lst=NULL;
 end=NULL;
 cur=node->first;
 while(cur)
 {
  t2=NetParse_CopyNode(cur);
  if(end)end->next=t2;
  end=t2;

  if(!lst)lst=end;
  cur=cur->next;
 }
 tmp->first=lst;

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_FindKey(NetParse_Node *first, char *key);
Description
 Finds a node in a list with a given key.
 Returns NULL if not found.
--*/
NetParse_Node *NetParse_FindKey(NetParse_Node *first, char *key)
{
 NetParse_Node *cur;

 cur=first;
 while(cur)
 {
  if(cur->key)
   if(!strcmp(cur->key, key))
    return(cur);
  cur=cur->next;
 }
 return(NULL);
}

//abstract interface funcs

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_NewNodeKey(char *ns, char *key);
Description
 Creates a new node with a given namespace prefix and key.
 ns may be NULL in most cases (the tag does not have a namespace  prefix).
--*/
NetParse_Node *NetParse_NewNodeKey(char *ns, char *key)
{
 NetParse_Node *tmp;

 tmp=NetParse_NewNode();
 tmp->key=kstrdup(key);

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 NetParse_Node *NetParse_NewNodeText(char *text);
Description
 Creates a new text node with the contents given.
--*/
NetParse_Node *NetParse_NewNodeText(char *text)
{
 NetParse_Node *tmp;

 tmp=NetParse_NewNode();
 tmp->text=kstrdup(text);

 return(tmp);
}

/*--
Cat pdlib;Parse
Form
 char *NetParse_GetNodeNS(NetParse_Node *node);
 char *NetParse_GetNodeKey(NetParse_Node *node);
 char *NetParse_GetNodeText(NetParse_Node *node);
 NetParse_Node *NetParse_GetNodeFirst(NetParse_Node *node);
 NetParse_Node *NetParse_GetNodeNext(NetParse_Node *node);
Description
 Get a property of a node, each will return NULL in the case that  the given property is not present.
--*/
char *NetParse_GetNodeNS(NetParse_Node *node)
{
 return(node->ns);
}

char *NetParse_GetNodeKey(NetParse_Node *node)
{
 return(node->key);
}

char *NetParse_GetNodeText(NetParse_Node *node)
{
 return(node->text);
}

NetParse_Node *NetParse_GetNodeFirst(NetParse_Node *node)
{
 return(node->first);
}

NetParse_Node *NetParse_GetNodeNext(NetParse_Node *node)
{
 return(node->next);
}

/*--
Cat pdlib;Parse
Form
 int NetParse_SetNodeNS(NetParse_Node *node, char *value);
 int NetParse_SetNodeKey(NetParse_Node *node, char *value);
 int NetParse_SetNodeText(NetParse_Node *node, char *value);
 int NetParse_SetNodeFirst(NetParse_Node *node, NetParse_Node *node2);
 int NetParse_SetNodeNext(NetParse_Node *node, NetParse_Node *node2);
Description
 Set a property of a node, the return value will be 0 if no errors  occure.
--*/
int NetParse_SetNodeNS(NetParse_Node *node, char *value)
{
 node->ns=kstrdup(value);
 return(0);
}

int NetParse_SetNodeKey(NetParse_Node *node, char *value)
{
 node->key=kstrdup(value);
 return(0);
}

int NetParse_SetNodeText(NetParse_Node *node, char *value)
{
 node->text=kstrdup(value);
 return(0);
}

int NetParse_SetNodeFirst(NetParse_Node *node, NetParse_Node *node2)
{
 node->first=node2;
 return(0);
}

int NetParse_SetNodeNext(NetParse_Node *node, NetParse_Node *node2)
{
 node->next=node2;
 return(0);
}





transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent