// MyXml.cpp #include "StdAfx.h" #include "MyXml.h" static bool IsValidChar(char c) { return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-'; } static bool IsSpaceChar(char c) { return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A); } #define SKIP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) { prop.Name.Empty(); prop.Value.Empty(); for (; pos < s.Length(); pos++) { char c = s[pos]; if (!IsValidChar(c)) break; prop.Name += c; } if (prop.Name.IsEmpty()) return false; SKIP_SPACES(s, pos); if (s[pos++] != '=') return false; SKIP_SPACES(s, pos); if (s[pos++] != '\"') return false; while (pos < s.Length()) { char c = s[pos++]; if (c == '\"') return true; prop.Value += c; } return false; } int CXmlItem::FindProperty(const AString &propName) const { for (int i = 0; i < Props.Size(); i++) if (Props[i].Name == propName) return i; return -1; } AString CXmlItem::GetPropertyValue(const AString &propName) const { int index = FindProperty(propName); if (index >= 0) return Props[index].Value; return AString(); } bool CXmlItem::IsTagged(const AString &tag) const { return (IsTag && Name == tag); } int CXmlItem::FindSubTag(const AString &tag) const { for (int i = 0; i < SubItems.Size(); i++) if (SubItems[i].IsTagged(tag)) return i; return -1; } AString CXmlItem::GetSubString() const { if (SubItems.Size() == 1) { const CXmlItem &item = SubItems[0]; if (!item.IsTag) return item.Name; } return AString(); } AString CXmlItem::GetSubStringForTag(const AString &tag) const { int index = FindSubTag(tag); if (index >= 0) return SubItems[index].GetSubString(); return AString(); } bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) { if (numAllowedLevels == 0) return false; SubItems.Clear(); AString finishString = "'); } if (s[pos] == '>') { if (!ParseItems(s, ++pos, numAllowedLevels)) return false; AString finishString = AString(""); if (s.Mid(pos, finishString.Length()) != finishString) return false; pos += finishString.Length(); return true; } if (posTemp == pos) return false; CXmlProp prop; if (!ReadProperty(s, pos, prop)) return false; Props.Add(prop); posTemp = pos; } } static bool SkipHeader(const AString &s, int &pos, const AString &startString, const AString &endString) { SKIP_SPACES(s, pos); if (s.Mid(pos, startString.Length()) == startString) { pos = s.Find(endString, pos); if (pos < 0) return false; pos += endString.Length(); SKIP_SPACES(s, pos); } return true; } bool CXml::Parse(const AString &s) { int pos = 0; if (!SkipHeader(s, pos, "")) return false; if (!SkipHeader(s, pos, "")) return false; if (!Root.ParseItem(s, pos, 1000)) return false; SKIP_SPACES(s, pos); return (pos == s.Length() && Root.IsTag); }