📄 pxml.cxx
字号:
OnLoaded();
}
return stat;
}
BOOL PXML::Save(int _options)
{
if (_options >= 0)
options = _options;
if (!loadFromFile || !IsDirty())
return FALSE;
return SaveFile(loadFilename);
}
BOOL PXML::SaveFile(const PFilePath & fn, int _options)
{
PWaitAndSignal m(rootMutex);
PFile file;
if (!file.Open(fn, PFile::WriteOnly))
return FALSE;
PString data;
if (!Save(data, _options))
return FALSE;
return file.Write((const char *)data, data.GetLength());
}
BOOL PXML::Save(PString & data, int _options)
{
PWaitAndSignal m(rootMutex);
if (_options >= 0)
options = _options;
PStringStream strm;
strm << *this;
data = strm;
return TRUE;
}
void PXML::RemoveAll()
{
PWaitAndSignal m(rootMutex);
if (rootElement != NULL) {
delete rootElement;
rootElement = NULL;
}
}
PXMLElement * PXML::GetElement(const PCaselessString & name, PINDEX idx) const
{
if (rootElement == NULL)
return NULL;
return rootElement->GetElement(name, idx);
}
PXMLElement * PXML::GetElement(PINDEX idx) const
{
if (rootElement == NULL)
return NULL;
if (idx >= rootElement->GetSize())
return NULL;
return (PXMLElement *)(rootElement->GetElement(idx));
}
BOOL PXML::RemoveElement(PINDEX idx)
{
if (rootElement == NULL)
return FALSE;
if (idx >= rootElement->GetSize())
return FALSE;
rootElement->RemoveElement(idx);
return TRUE;
}
PINDEX PXML::GetNumElements() const
{
if (rootElement == NULL)
return 0;
else
return rootElement->GetSize();
}
BOOL PXML::IsNoIndentElement(const PString & elementName) const
{
return noIndentElements.GetValuesIndex(elementName) != P_MAX_INDEX;
}
void PXML::PrintOn(ostream & strm) const
{
BOOL newLine = (options & (PXMLParser::Indent|PXMLParser::NewLineAfterElement)) != 0;
//<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
PString ver = version;
PString enc = encoding;
int salone = standAlone;
if (ver.IsEmpty())
ver= "1.0";
if (enc.IsEmpty())
enc = "UTF-8";
if (salone == -2)
salone = -1;
strm << "<?xml version=\"" << ver << "\" encoding=\"" << enc << "\"";
switch (salone) {
case 0:
strm << " standalone=\"no\"";
break;
case 1:
strm << " standalone=\"yes\"";
break;
default:
break;
}
strm << "?>";
if (newLine)
strm << endl;
if (rootElement != NULL) {
if (!docType.IsEmpty())
strm << "<!DOCTYPE " << docType << '>';
if (newLine)
strm << endl;
rootElement->Output(strm, *this, 2);
}
}
PString PXML::CreateStartTag(const PString & text)
{
return '<' + text + '>';
}
PString PXML::CreateEndTag(const PString & text)
{
return "</" + text + '>';
}
PString PXML::CreateTagNoData(const PString & text)
{
return '<' + text + "/>";
}
PString PXML::CreateTag(const PString & text, const PString & data)
{
return CreateStartTag(text) + data + CreateEndTag(text);
}
///////////////////////////////////////////////////////
//
void PXMLObject::SetDirty()
{
dirty = TRUE;
if (parent != NULL)
parent->SetDirty();
}
PXMLObject * PXMLObject::GetNextObject()
{
if (parent == NULL)
return NULL;
// find our index in our parent's list
PINDEX idx = parent->FindObject(this);
if (idx == P_MAX_INDEX)
return NULL;
// get the next object
++idx;
if (idx >= parent->GetSize())
return NULL;
return (*parent).GetElement(idx);
}
///////////////////////////////////////////////////////
PXMLData::PXMLData(PXMLElement * _parent, const PString & _value)
: PXMLObject(_parent)
{
value = _value;
}
PXMLData::PXMLData(PXMLElement * _parent, const char * data, int len)
: PXMLObject(_parent)
{
value = PString(data, len);
}
void PXMLData::Output(ostream & strm, const PXMLBase & xml, int indent) const
{
int options = xml.GetOptions();
if (xml.IsNoIndentElement(parent->GetName()))
options &= ~PXMLParser::Indent;
if (options & PXMLParser::Indent)
strm << setw(indent-1) << " ";
strm << value;
if ((options & (PXMLParser::Indent|PXMLParser::NewLineAfterElement)) != 0)
strm << endl;
}
void PXMLData::SetString(const PString & str, BOOL setDirty)
{
value = str;
if (setDirty)
SetDirty();
}
PXMLObject * PXMLData::Clone(PXMLElement * _parent) const
{
return new PXMLData(_parent, value);
}
///////////////////////////////////////////////////////
PXMLElement::PXMLElement(PXMLElement * _parent, const char * _name)
: PXMLObject(_parent)
{
dirty = FALSE;
if (_name != NULL)
name = _name;
}
PXMLElement::PXMLElement(PXMLElement * _parent, const PString & _name, const PString & data)
: PXMLObject(_parent), name(_name)
{
dirty = FALSE;
AddSubObject(new PXMLData(this, data));
}
PINDEX PXMLElement::FindObject(PXMLObject * ptr) const
{
return subObjects.GetObjectsIndex(ptr);
}
PXMLElement * PXMLElement::GetElement(const PCaselessString & name, PINDEX start) const
{
PINDEX idx;
PINDEX size = subObjects.GetSize();
PINDEX count = 0;
for (idx = 0; idx < size; idx++) {
if (subObjects[idx].IsElement()) {
PXMLElement & subElement = ((PXMLElement &)subObjects[idx]);
if (subElement.GetName() *= name) {
if (count++ == start)
return (PXMLElement *)&subObjects[idx];
}
}
}
return NULL;
}
PXMLObject * PXMLElement::GetElement(PINDEX idx) const
{
if (idx >= subObjects.GetSize())
return NULL;
return &subObjects[idx];
}
BOOL PXMLElement::RemoveElement(PINDEX idx)
{
if (idx >= subObjects.GetSize())
return FALSE;
subObjects.RemoveAt(idx);
return TRUE;
}
PString PXMLElement::GetAttribute(const PCaselessString & key) const
{
return attributes(key);
}
PString PXMLElement::GetKeyAttribute(PINDEX idx) const
{
if (idx < attributes.GetSize())
return attributes.GetKeyAt(idx);
else
return PString();
}
PString PXMLElement::GetDataAttribute(PINDEX idx) const
{
if (idx < attributes.GetSize())
return attributes.GetDataAt(idx);
else
return PString();
}
void PXMLElement::SetAttribute(const PCaselessString & key,
const PString & value,
BOOL setDirty)
{
attributes.SetAt(key, value);
if (setDirty)
SetDirty();
}
BOOL PXMLElement::HasAttribute(const PCaselessString & key)
{
return attributes.Contains(key);
}
void PXMLElement::PrintOn(ostream & strm) const
{
PXMLBase xml(-1);
Output(strm, xml, 0);
}
void PXMLElement::Output(ostream & strm, const PXMLBase & xml, int indent) const
{
int options = xml.GetOptions();
BOOL newLine = (options & (PXMLParser::Indent|PXMLParser::NewLineAfterElement)) != 0;
if ((options & PXMLParser::Indent) != 0)
strm << setw(indent-1) << " ";
strm << '<' << name;
PINDEX i;
if (attributes.GetSize() > 0) {
for (i = 0; i < attributes.GetSize(); i++) {
PCaselessString key = attributes.GetKeyAt(i);
strm << ' ' << key << "=\"" << attributes[key] << '"';
}
}
// this ensures empty elements use the shortened form
if (subObjects.GetSize() == 0) {
strm << "/>";
if (newLine)
strm << endl;
}
else {
BOOL indenting = (options & PXMLParser::Indent) != 0 && !xml.IsNoIndentElement(name);
strm << '>';
if (indenting)
strm << endl;
for (i = 0; i < subObjects.GetSize(); i++)
subObjects[i].Output(strm, xml, indent + 2);
if (indenting)
strm << setw(indent-1) << " ";
strm << "</" << name << '>';
if (newLine)
strm << endl;
}
}
PXMLObject * PXMLElement::AddSubObject(PXMLObject * elem, BOOL setDirty)
{
subObjects.SetAt(subObjects.GetSize(), elem);
if (setDirty)
SetDirty();
return elem;
}
PXMLElement * PXMLElement::AddChild(PXMLElement * elem, BOOL dirty)
{
return (PXMLElement *)AddSubObject(elem, dirty);
}
PXMLData * PXMLElement::AddChild(PXMLData * elem, BOOL dirty)
{
return (PXMLData *)AddSubObject(elem, dirty);
}
PXMLObject * PXMLElement::Clone(PXMLElement * _parent) const
{
PXMLElement * elem = new PXMLElement(_parent);
elem->SetName(name);
elem->attributes = attributes;
elem->dirty = dirty;
PINDEX idx;
for (idx = 0; idx < subObjects.GetSize(); idx++)
elem->AddSubObject(subObjects[idx].Clone(elem), FALSE);
return elem;
}
PString PXMLElement::GetData() const
{
PString str;
PINDEX idx;
for (idx = 0; idx < subObjects.GetSize(); idx++) {
if (!subObjects[idx].IsElement()) {
PXMLData & dataElement = ((PXMLData &)subObjects[idx]);
PStringArray lines = dataElement.GetString().Lines();
PINDEX j;
for (j = 0; j < lines.GetSize(); j++)
str = str & lines[j];
}
}
return str;
}
///////////////////////////////////////////////////////
PXMLSettings::PXMLSettings(int options)
:PXML(options)
{
}
PXMLSettings::PXMLSettings(const PString & data, int options)
: PXML(data,options)
{
}
PXMLSettings::PXMLSettings(const PConfig & data, int options)
: PXML(options)
{
PStringList sects = data.GetSections();
for (PINDEX i = 0;i < (PINDEX)sects.GetSize();++i) {
PStringToString keyvals = data.GetAllKeyValues(sects[i]);
for (PINDEX j = 0; j < (PINDEX)keyvals.GetSize(); ++j) {
SetAttribute(sects[i],keyvals.GetKeyAt(j),keyvals.GetDataAt(j));
}
}
}
BOOL PXMLSettings::Load(const PString & data)
{
return PXML::Load(data);
}
BOOL PXMLSettings::LoadFile(const PFilePath & fn)
{
return PXML::LoadFile(fn);
}
BOOL PXMLSettings::Save()
{
return PXML::Save();
}
BOOL PXMLSettings::Save(PString & data)
{
return PXML::Save(data);
}
BOOL PXMLSettings::SaveFile(const PFilePath & fn)
{
return PXML::SaveFile(fn);
}
PString PXMLSettings::GetAttribute(const PCaselessString & section, const PString & key) const
{
if (rootElement == NULL)
return PString();
PXMLElement * element = rootElement->GetElement(section);
if (element == NULL)
return PString();
return element->GetAttribute(key);
}
void PXMLSettings::SetAttribute(const PCaselessString & section, const PString & key, const PString & value)
{
if (rootElement == NULL)
rootElement = new PXMLElement(NULL, "settings");
PXMLElement * element = rootElement->GetElement(section);
if (element == NULL) {
element = new PXMLElement(rootElement, section);
rootElement->AddSubObject(element);
}
element->SetAttribute(key, value);
}
BOOL PXMLSettings::HasAttribute(const PCaselessString & section, const PString & key) const
{
if (rootElement == NULL)
return FALSE;
PXMLElement * element = rootElement->GetElement(section);
if (element == NULL)
return FALSE;
return element->HasAttribute(key);
}
void PXMLSettings::ToConfig(PConfig & cfg) const
{
for (PINDEX i = 0;i < (PINDEX)GetNumElements();++i) {
PXMLElement * el = GetElement(i);
PString sectionName = el->GetName();
for (PINDEX j = 0; j < (PINDEX)el->GetNumAttributes(); ++j) {
PString key = el->GetKeyAttribute(j);
PString dat = el->GetDataAttribute(j);
if (!key && !dat)
cfg.SetString(sectionName, key, dat);
}
}
}
///////////////////////////////////////////////////////
PXMLStreamParser::PXMLStreamParser() :
rootOpen(TRUE)
{
}
void PXMLStreamParser::EndElement(const char * name)
{
PXMLElement * element = currentElement;
PXMLParser::EndElement(name);
if (currentElement == rootElement) {
if (element == rootElement) { // stream closed
rootOpen = FALSE;
}
else {
PINDEX i = rootElement->FindObject(element);
if (i != P_MAX_INDEX) {
PXML tmp;
element = (PXMLElement *)element->Clone(0);
rootElement->RemoveElement(i);
PXML * msg = new PXML;
msg->SetRootElement(element);
messages.Enqueue(msg);
}
}
}
}
PXML * PXMLStreamParser::Read(PChannel * channel)
{
char buf[256];
channel->SetReadTimeout(1000);
while (rootOpen) {
if (messages.GetSize() != 0)
return messages.Dequeue();
if (!channel->Read(buf, sizeof(buf) - 1) || !channel->IsOpen())
return 0;
buf[channel->GetLastReadCount()] = 0;
if (!Parse(buf, channel->GetLastReadCount(), FALSE))
return 0;
}
channel->Close();
return 0;
}
///////////////////////////////////////////////////////
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -