XMLNode::XMLNode(const String &S)
{
Init(S);
}
XMLNode::~XMLNode()
{
FreeMemory();
}
void XMLNode::FreeMemory()
{
Attributes.FreeMemory();
for(UINT ChildIndex = 0; ChildIndex < Children.Length(); ChildIndex++)
{
delete Children[ChildIndex];
}
Children.FreeMemory();
}
void XMLNode::Save(ofstream &File)
{
if(Name == "@DELETED")
{
return;
}
if(Name == "Root")
{
for(UINT ChildIndex = 0; ChildIndex < Children.Length(); ChildIndex++)
{
Children[ChildIndex]->Save(File);
}
}
else
{
File << "<" << Name;
for(UINT AttributeIndex = 0; AttributeIndex < Attributes.Length(); AttributeIndex++)
{
const XMLAttribute &CurAttribute = Attributes[AttributeIndex];
File << ' ' << CurAttribute.Name << "=\"" << CurAttribute.Value << "\"";
}
if(Children.Length() == 0)
{
File << "/>" << endl;
}
else
{
File << '>' << endl;
for(UINT ChildIndex = 0; ChildIndex < Children.Length(); ChildIndex++)
{
Children[ChildIndex]->Save(File);
}
File << "</" << Name << '>' << endl;
}
}
}
void XMLNode::Init(const String &S)
{
if(S[0] == '?')
{
Name = "?xml";
}
else
{
Vector<String> Words;
S.Partition(' ', Words);
if(Words.Length() == 0 || Words[0].Length() == 0)
{
SignalError("Invalid node header");
}
Name = Words[0];
if(Words.Length() >= 2)
{
S.Partition('\"', Words, true);
if(Words.Last() == " ")
{
Words.PopEnd();
}
if(Words.Length() % 2 != 0)
{
SignalError("Invalid node header");
}
String P0, P1;
Words[0].PartitionAboutIndex(Words[0].FindFirstIndex(' '), P0, P1);
Assert(P0 == Name, "Invalid node header");
Words[0] = P1;
const UINT AttributeCount = Words.Length() / 2;
Attributes.Allocate(AttributeCount);
for(UINT AttributeIndex = 0; AttributeIndex < AttributeCount; AttributeIndex++)
{
XMLAttribute &CurAttribute = Attributes[AttributeIndex];
CurAttribute.Name = Words[AttributeIndex * 2 + 0];
Assert(CurAttribute.Name.Last() == '=', "Invalid node header");
CurAttribute.Name.PopEnd();
while(CurAttribute.Name[0] == ' ')
{
CurAttribute.Name.PopFront();
}
CurAttribute.Value = Words[AttributeIndex * 2 + 1];
}
}
}
}
void XMLNode::MakeChildEntryList(Vector<XMLSchemaChildEntry> &List) const
{
List.FreeMemory();
for(UINT ChildIndex = 0; ChildIndex < Children.Length(); ChildIndex++)
{
const XMLNode &CurChild = *(Children[ChildIndex]);
String CStyleChildName = XMLNameToCStyleName(CurChild.Name);
bool ChildNameFound = false;
for(UINT ListIndex = 0; ListIndex < List.Length() && !ChildNameFound; ListIndex++)
{
if(List[ListIndex].Name == CStyleChildName)
{
List[ListIndex].Count++;
ChildNameFound = true;
}
}
if(!ChildNameFound)
{
List.PushEnd(XMLSchemaChildEntry(CStyleChildName));
}
}
}
void XMLNode::GetChildrenByName(const String &Name, Vector<XMLNode*> &Result) const
{
Result.FreeMemory();
for(UINT ChildIndex = 0; ChildIndex < Children.Length(); ChildIndex++)
{
if(Children[ChildIndex]->Name == Name)
{
Result.PushEnd(Children[ChildIndex]);
}
}
}
String XMLNode::GetAttributeByName(const String &Name) const
{
for(UINT AttributeIndex = 0; AttributeIndex < Attributes.Length(); AttributeIndex++)
{
if(Attributes[AttributeIndex].Name == Name)
{
return Attributes[AttributeIndex].Value;
}
}
return String();
}