/* * This is a very simple, hard-coded and limited XML parser, which parses XML from file into local variable. * Made for illustrative purposes. */ #include #include #include class Tag { public: // щото да не се занимавам с гетъри и сетъри char name[64]; // char id[64]; char value[64]; Tag* children; unsigned length; unsigned count; private: void copyFrom(const Tag& other) { strncpy(name, other.name, 64); strncpy(value, other.value, 64); children = new Tag[other.length]; for (unsigned i = 0; i < other.count; i++) children[i] = other.children[i]; length = other.length; count = other.count; } void free() { delete[] children; } void resize() { if (length == 0) length = 4; Tag* tmp = new Tag[length <<= 1]; for (unsigned i = 0; i < count; i++) tmp[i] = children[i]; delete[] children; children = tmp; } public: void addChild(const Tag& child) { if (length == count) resize(); children[count++] = child; } Tag() { children = nullptr; length = count = 0; } Tag(const Tag& other) { copyFrom(other); } Tag& operator=(const Tag& other) { if (this != &other) { free(); copyFrom(other); } return *this; } ~Tag() { free(); } }; void parseTag(Tag& root, std::ifstream& file) { Tag newTag; // Вземаме името на тага (все едно всичко между < и >) // важно: предполагаме, че вече сме минали < и от сега до > е само името на тага char buffer = '<'; for (unsigned i = 0; i < 63 && file.peek() != '>'; i++) { buffer = file.get(); newTag.name[i] = buffer; newTag.name[i + 1] = '\0'; } file.get(); // ние сме на знак >, затова отиваме на следващия // ако следващия не е <, то имаме някаква стойност, която ще запазим for (unsigned i = 0; i < 63 && file.peek() != '<'; i++) { buffer = file.get(); newTag.value[i] = buffer; newTag.value[i + 1] = '\0'; } file.get(); // ние сме на знак <, затова отиваме на следващия // предишния знак е <, тоест, ако сегашния е /, то имаме ), сега просто ще скипнем името му for (unsigned i = 0; file.peek() != '>'; i++) file.get(); file.get(); // знаем, че сме на >, затова отиваме на следващия file.get(); // ако има съседни тагове, то в момента ще сме на <, затова и него го скипваме root.addChild(newTag); } void printTag(Tag& tag, unsigned level = 0) { for (unsigned i = 0; i < level; i++) std::cout << " "; std::cout << "<" << tag.name << ">" << " " << tag.value << std::endl; level++; for (unsigned i = 0; i < tag.count; i++) printTag(tag.children[i], level); } int main() { std::ifstream inFile("test.xml"); inFile.get(); Tag root; parseTag(root, inFile); printTag(root); inFile.close(); }