//下面的代码可以每次获取一个标签元素,每个元素包含多个属性值对
//只支持不带结束标签的xml,如:<path file="C://1.txt"> 或者<path file=C://1.txt>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <iostream>
typedef struct Property
{
char *name_;
char *value_;
Property *next_;
}Property;
typedef struct Element
{
char *element_name_;
Property *prop_;
}Element;
Property *GetParameters(const char* input)
{
Property *head = NULL;
Property *cur_prop = head;
while(*input) {
std::string name;
while(*input && isspace(*input))
++input;
while(*input && !isspace(*input) && *input != '=') {
name += *input;
++input;
}
while(*input && isspace(*input))
++input;
if(*input) {
if(*input != '=')
{
//失败
break;
}
else
++input;
}
Property *prop = (Property *)malloc(sizeof(Property));
memset(prop, 0, sizeof(Property));
if (cur_prop)
{
cur_prop->next_ = prop;
}
else
{
head = prop;
cur_prop = prop;
}
int len = name.size() + 1;
prop->name_ = (char *)malloc(len);
memset(prop->name_, 0, len);
strcpy(prop->name_, name.c_str());
//获取value
std::string value = "";
while(*input && isspace(*input))
++input;
if(*input && *input == '\"') {
++input;
while(*input && *input != '\"') {
value += *input++;
}
if(*input && *input == '\"')
++input;
} else {
while(*input && !isspace(*input))
name += *input++;
}
len = value.size() + 1;
prop->value_ = (char *)malloc(len);
memset(prop->value_, 0, len);
strcpy(prop->value_, value.c_str());
}
return head;
}
Element *HandleTag(const std::string& tag)
{
if(tag.empty())
return NULL;
size_t i;
for(i = 0; i < tag.length(); ++i)
{
if(isspace(tag[i]))
continue;
else
break;
}
if(i == tag.length())
return NULL;
Element *elem = (Element *)malloc(sizeof(Element));
memset(elem, 0, sizeof(Element));
std::string tagName;
for( ; i != tag.length(); ++i) {
if(!isspace(tag[i]))
tagName += tag[i];
else
break;
}
int len = tagName.size() + 1;
elem->element_name_ = (char *)malloc(len);
memset(elem->element_name_, 0, len);
strcpy(elem->element_name_, tagName.c_str());
Property *prop = GetParameters(tag.c_str() + i);
elem->prop_ = prop;
return elem;
}
Element *Parse(FILE *f)
{
bool inquote = false;
bool intag = false;
std::string tag = "";
Element *elem = NULL;
int c;
while(c = fgetc(f)) {
if (feof(f)) {
break;
}
switch(c) {
case '\"':
inquote = !inquote;
break;
case '<':
if(!inquote) {
intag = true;
tag = "";
continue; //不能换成break;
}
case '>':
if(!inquote)
{
elem = HandleTag(tag);
intag = false;
return elem; //不能换成break;
}
}
if(intag)
tag += (char)c;
}
return elem;
}
void DelElement(Element *elem)
{
if (!elem)
{
return;
}
Property *next_prop = elem->prop_;
while (next_prop)
{
Property *cur_prop = next_prop;
next_prop = next_prop->next_;
if (cur_prop->name_)
{
free(cur_prop->name_);
cur_prop->name_ = NULL;
}
if (cur_prop->value_)
{
free(cur_prop->value_);
cur_prop->value_ = NULL;
}
free(cur_prop);
}
}
int main(int argc, char *argv[])
{
FILE *fd = fopen(argv[1], "rb");
Element *elem = NULL;
while (elem = Parse(fd))
{
std::cout<<">elem name: "<< elem->element_name_<< std::endl;
Property *prop = elem->prop_;
while (prop)
{
std::cout<<">>>prop name :"<<prop->name_<<std::endl;
std::cout<<">>>prop value :"<<prop->value_<<std::endl;
prop = prop->next_;
}
DelElement(elem);
}
fclose(fd);
return 0;
}