代码拉取完成,页面将自动刷新
//----------------------------------------------------------------------
// XmlElement.cpp:
// Definition of XML file operation class
//
// Copyright (C) 2020-2029 by Jun Mo, All rights reserved.
//
//----------------------------------------------------------------------
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "XmlElement.h"
CSimpleDict::CSimpleDict()
{
DictItemNumber = 0;
Dictionary = (DictItem *)malloc(sizeof(DictItem) * DICT_ITEM_INC);
DictArraySize = DICT_ITEM_INC;
}
CSimpleDict::~CSimpleDict()
{
free(Dictionary);
}
CSimpleDict& CSimpleDict::operator=(const CSimpleDict& dict)
{
if (DictArraySize != dict.DictArraySize)
{
DictArraySize = dict.DictArraySize;
DictItemNumber = dict.DictItemNumber;
Dictionary = (DictItem *)realloc(Dictionary, sizeof(DictItem) * DictArraySize);
}
memcpy(Dictionary, dict.Dictionary, sizeof(DictItem) * DictItemNumber);
return *this;
}
bool CSimpleDict::Add(char *key, char *value)
{
DictItem *NewDict;
if (strlen(key) > MAX_KEY_LENGTH || strlen(value) > MAX_VALUE_LENGTH)
return false;
if (DictItemNumber == DictArraySize)
{
DictArraySize += DICT_ITEM_INC;
NewDict = (DictItem *)realloc(Dictionary, sizeof(DictItem) * DictArraySize);
if (NewDict == NULL)
return false;
Dictionary = NewDict;
}
strcpy(Dictionary[DictItemNumber].key, key);
strcpy(Dictionary[DictItemNumber].value, value);
DictItemNumber ++;
return true;
}
bool CSimpleDict::Delete(char *key)
{
int index;
index = Find(key);
if (index < 0)
return false;
if (index != (DictItemNumber - 1))
memmove(Dictionary + index, Dictionary + index + 1, sizeof(DictItem) * (DictItemNumber - index - 1));
DictItemNumber --;
return true;
}
int CSimpleDict::Find(char *key)
{
int i;
for (i = 0; i < DictItemNumber; i ++)
if (strcmp(Dictionary[i].key, key) == 0)
break;
return (i == DictItemNumber) ? -1 : i;
}
CXmlElement::CXmlElement()
{
tag[0] = 0;
text[0] = 0;
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::CXmlElement(CXmlElement &element)
{
strcpy(this->tag, element.tag);
strcpy(this->text, element.text);
this->Attributes = element.Attributes;
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::CXmlElement(char *tag, char *text)
{
strcpy(this->tag, tag);
strcpy(this->text, text);
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::~CXmlElement()
{
DeleteTree();
}
bool CXmlElement::DeleteTree()
{
if (ChildElements)
{
ChildElements->DeleteTree();
delete ChildElements;
ChildElements = NULL;
}
if (SiblingElements)
{
SiblingElements->DeleteTree();
delete SiblingElements;
SiblingElements = NULL;
}
return true;
}
bool CXmlElement::RemoveElement(int index)
{
CXmlElement *PrevElement = NULL, *CurElement = NULL;
if (index < 0)
return false;
if (index == 0)
{
PrevElement = NULL;
CurElement = ChildElements;
}
else
{
PrevElement = GetElement(index-1);
CurElement = PrevElement->SiblingElements;
}
if (!CurElement)
return false;
// remove current element from link list
if (PrevElement)
PrevElement->SiblingElements = CurElement->SiblingElements;
else
ChildElements = CurElement->SiblingElements;
// delete current element
CurElement->DeleteTree();
delete CurElement;
return true;
}
CXmlElement * CXmlElement::GetElement(int index)
{
CXmlElement *Element = ChildElements;
while (Element && index > 0)
{
Element = Element->SiblingElements;
index --;
}
return Element;
}
bool CXmlElement::parse_string(char *string, bool with_tag)
{
char *str = string;
char *p;
CXmlElement *SubElement;
// trim empty characters
while (*str && (*str == ' ' || *str == '\t'))
str ++;
// for string passed in with tag of current element, first extract tag
if (with_tag)
str = process_tag(str);
if (*str == 0)
return Completed;
if (!Completed) // find text
{
// trim empty characters
while (*str && (*str == ' ' || *str == '\t'))
str ++;
// whether followed with '<'
if ((p = strchr(str, '<')) != NULL)
*p = 0;
if (*str && (p ? (p > str) : true))
strcpy(text, str);
// put str to end of text
if (p)
{
*p = '<'; // restore '<'
str = p;
}
else
*str = 0;
}
if (*str != '<')
return Completed;
if (Completed) // for completed element, drop any following character
return true;
p = strchr(str, '>');
if (!p)
return Completed;
// whether this is end of element
if (str[1] == '/')
{
*p = 0;
if (strcmp(tag, str + 2) == 0)
{
Completed = true;
return true;
}
// not end of current element, restore '>'
*p = '>';
// pass to active sub-element
SubElement = GetElement(iChildNumber - 1);
if (SubElement && !(SubElement->Completed))
SubElement->parse_string(str, false);
}
else // this is a new tag
{
// create a new sub-element
if (iChildNumber > 0)
{
SubElement = GetElement(iChildNumber - 1);
if (SubElement->Completed)
{
SubElement->SiblingElements = new CXmlElement;
SubElement = SubElement->SiblingElements;
iChildNumber ++;
}
}
else
{
ChildElements = new CXmlElement;
SubElement = ChildElements;
iChildNumber ++;
}
SubElement->parse_string(str, SubElement->Completed);
}
return Completed;
}
char *CXmlElement::process_tag(char *string)
{
char *left, *right;
char *p;
left = strchr(string, '<');
right = strchr(string, '>');
if (left[1] == '/')
return NULL;
p = left + 1;
while (*p != ' ' && *p != '\t' && *p != '>')
p ++;
*p = 0;
strcpy(tag, left + 1);
p ++;
while (*p && *p != '>')
{
// trim empty characters
while (*p && (*p == ' ' || *p == '\t'))
p ++;
if ((left = strchr(p, '=')) == NULL) // do not find '='
break;
*left = 0;
left ++;
// find contents with in ""
left = strchr(left, '"');
if (!left)
break;
left ++;
right = strchr(left, '"');
if (!right)
break;
*right = 0;
Attributes.Add(p, left);
p = right + 1;
}
if (*p == '/' && p[1] == '>')
{
p ++;
Completed = true;
}
else
Completed = false;
return (*p == '>') ? p + 1 : p;
}
bool CXmlElement::output(FILE *fp, int indent)
{
CXmlElement *Elements;
int i;
// no text and no sub-element
if (strlen(text) == 0 && iChildNumber == 0)
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, "/>\n");
return true;
}
// no sub-element
else if (iChildNumber == 0)
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, ">");
fprintf(fp, "%s", text);
fprintf(fp, "</%s>\n", tag);
return true;
}
else
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, ">\n");
if (strlen(text) > 0)
fprintf(fp, "%s\n", text);
Elements = ChildElements;
while (Elements)
{
Elements->output(fp, indent + 1);
Elements = Elements->SiblingElements;
}
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "</%s>\n", tag);
return true;
}
}
bool CXmlElement::AppendElement(CXmlElement element)
{
CXmlElement *NewElement;
if (iChildNumber == 0)
NewElement = ChildElements = new CXmlElement(element);
else
{
NewElement = ChildElements;
while (NewElement->SiblingElements)
NewElement = NewElement->SiblingElements;
NewElement->SiblingElements = new CXmlElement(element);
NewElement = NewElement->SiblingElements;
}
iChildNumber ++;
NewElement->ChildElements = NewElement->SiblingElements = NULL;
NewElement->iChildNumber = 0;
return true;
}
bool CXmlElement::AppendElement(char *tag, char *text)
{
CXmlElement NewElement(tag, text);
return AppendElement(NewElement);
}
bool CXmlElement::InsertElement(int index, CXmlElement element)
{
CXmlElement *CurElement = NULL, *NewElement;
if (index > 0)
CurElement = GetElement(index-1);
else
CurElement = ChildElements;
if (!CurElement && iChildNumber > 0)
return false;
NewElement = new CXmlElement(element);
if (iChildNumber == 0)
ChildElements = NewElement;
else if (index == 0)
{
ChildElements = NewElement;
NewElement->SiblingElements = CurElement;
}
else
{
NewElement->SiblingElements = CurElement->SiblingElements;
CurElement->SiblingElements = NewElement;
}
iChildNumber ++;
return true;
}
bool CXmlElement::SetTag(char *tag)
{
if (strlen(tag) > MAX_TAG_LENGTH)
return false;
strcpy(this->tag, tag);
return true;
}
bool CXmlElement::SetText(char *text)
{
if (strlen(text) > MAX_TEXT_LENGTH)
return false;
strcpy(this->text, text);
return true;
}
CXmlElementTree::CXmlElementTree()
{
root = NULL;
header[0] = 0;
comment[0] = 0;
}
CXmlElementTree::CXmlElementTree(CXmlElement element)
{
root = new CXmlElement;
*root = element;
header[0] = 0;
comment[0] = 0;
}
CXmlElementTree::~CXmlElementTree()
{
ClearTree();
}
void CXmlElementTree::SetRootElement(CXmlElement element)
{
ClearTree();
root = new CXmlElement;
*root = element;
}
void CXmlElementTree::ClearTree()
{
if (root)
{
root->DeleteTree();
delete root;
root = NULL;
}
}
bool CXmlElementTree::parse(char *filename)
{
FILE *fp;
char string[512], *content;
if ((fp = fopen(filename, "r")) == NULL)
return false;
ClearTree();
while (!feof(fp))
{
fgets(string, 511, fp);
content = string + strlen(string) - 1;
while (*content == '\r' || *content == '\n')
*content -- = 0;
if (((content = found_header(string)) != NULL) && strlen(content) <= MAX_HEADER_LENGTH)
strcpy(header, content);
else if (((content = found_comment(string)) != NULL) && strlen(content) <= MAX_COMMENT_LENGTH)
strcpy(comment, content);
else if (root)
root->parse_string(string, false);
else if (found_tag(string))
{
root = new CXmlElement;
root->parse_string(string, true);
}
}
return true;
}
bool CXmlElementTree::write(char *filename)
{
FILE *fp = fopen(filename, "w");
if (!fp)
return false;
if (strlen(header) > 0)
fprintf(fp, "<?xml %s?>\n", header);
if (strlen(comment) > 0)
fprintf(fp, "<!-- %s-->\n", comment);
if (root)
root->output(fp, 0);
fclose(fp);
return true;
}
char *CXmlElementTree::found_header(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
if (!left || left[1] != '?')
return NULL;
if (right < string || right[-1] != '?')
return NULL;
if (left[2] != 'x' && left[2] != 'X')
return NULL;
if (left[3] != 'm' && left[3] != 'M')
return NULL;
if (left[4] != 'l' && left[4] != 'L')
return NULL;
// trim off end
right[-1] = 0;
left += 5;
// trim empty characters
while (*left && (*left == ' ' || *left == '\t'))
left ++;
return left;
}
char *CXmlElementTree::found_comment(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
if (!left || left[1] != '!')
return NULL;
if (left[2] != '-' || left[3] != '-')
return NULL;
if (right < string || right[-1] != '-' || right[-2] != '-')
return NULL;
// trim off end
right[-2] = 0;
left += 4;
// trim empty characters
while (*left && (*left == ' ' || *left == '\t'))
left ++;
return left;
}
bool CXmlElementTree::found_tag(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
return (left && right && right > left);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。