00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <fun/SerialTree.h>
00019
00020
00021 #ifdef HAVE_LIBXML
00022
00023 #include <fun/XMLUtil.h>
00024 #include <iostream>
00025 #include <gnome-xml/tree.h>
00026 #include <gnome-xml/parser.h>
00027
00028 namespace fun {
00029
00030
00031 static ostream &
00032 operator<<(ostream &os, xmlElementType t)
00033 {
00034 switch(t)
00035 {
00036 case XML_ELEMENT_NODE: os << "ELEMENT"; break;
00037 case XML_ATTRIBUTE_NODE: os << "ATTRIBUTE"; break;
00038 case XML_TEXT_NODE: os << "TEXT"; break;
00039 case XML_CDATA_SECTION_NODE: os << "CDATA_SECTION"; break;
00040 case XML_ENTITY_REF_NODE: os << "ENTITY_REF"; break;
00041 case XML_ENTITY_NODE: os << "ENTITY"; break;
00042 case XML_PI_NODE: os << "PI"; break;
00043 case XML_COMMENT_NODE: os << "COMMENT"; break;
00044 case XML_DOCUMENT_NODE: os << "DOCUMENT"; break;
00045 case XML_DOCUMENT_TYPE_NODE: os << "DOCUMENT_TYPE"; break;
00046 case XML_DOCUMENT_FRAG_NODE: os << "DOCUMENT_FRAG"; break;
00047 case XML_NOTATION_NODE: os << "NOTATION"; break;
00048 default: os << "(wha??)";
00049 }
00050 return os;
00051 }
00052
00053 static QString
00054 getSerializableClass(xmlNode *np)
00055 {
00056 return XMLUtil::getTextAttr(np, "class");
00057 }
00058
00059 static void
00060 setSerializableClass(xmlNode *np, const QString &cls)
00061 {
00062 XMLUtil::addTextAttr(np, "class", cls);
00063 }
00064
00065 SerialTree *
00066 SerialTree::loadFromXMLFile(const QString &filename)
00067 {
00068 xmlDoc *xdoc = xmlParseFile(filename);
00069 if(xdoc == NULL) return NULL;
00070
00071
00072 SerialTree *root = NULL;
00073 Child *cp = NULL;
00074 xmlNode *lastcmnt = NULL;
00075 for(xmlNode *xnp = xdoc->root; (xnp != NULL) && root == NULL; xnp = xnp->next)
00076 {
00077
00078 switch(xnp->type)
00079 {
00080 case XML_COMMENT_NODE:
00081 break;
00082 case XML_ELEMENT_NODE:
00083
00084 root = new SerialTree;
00085 cp = new Child((const char *)(xnp->name));
00086 childFromXMLNode(*cp, xnp);
00087 root->children.append(cp);
00088
00089 if(cp->tval) cp->tval->setSerializableClass(::getSerializableClass(xnp));
00090
00091 break;
00092 default:
00093 NOT_DONE("parseXML() doesn't handle node type " << xnp->type);
00094 }
00095 }
00096 return root;
00097 }
00098
00099 bool
00100 SerialTree::saveToXMLFile(const QString &filename, int mode)
00101 {
00102 xmlDoc *doc = XMLUtil::newDocument();
00103 NOT_DONE("saveToXMLFile() doesn't handle parent node right");
00104
00105
00106 toXMLNode((xmlNode *)doc);
00107
00108
00109
00110 XMLUtil::saveFile(doc, filename);
00111
00112 XMLUtil::deleteDocument(doc);
00113 NOT_DONE("saveToXMLFile() does no error checking");
00114 return true;
00115 }
00116
00117 void
00118 SerialTree::toXMLNode(void *xmlnode) const
00119 {
00120 xmlNode *np = (xmlNode *)xmlnode;
00121 if(!getSerializableClass().isNull()) ::setSerializableClass(np, getSerializableClass());
00122 for(QPtrListIterator<Child> it(children); it.current(); ++it)
00123 {
00124 xmlNode *cnp = XMLUtil::addChild(np, XML_ELEMENT_NODE, it.current()->key);
00125 if(it.current()->sval)
00126 {
00127 XMLUtil::addChild(cnp, XML_TEXT_NODE, *(it.current()->sval));
00128 }
00129 else if(it.current()->tval)
00130 {
00131 it.current()->tval->toXMLNode(cnp);
00132 }
00133 else
00134 {
00135 NOT_DONE("toXMLNode() doesn't handle stubby children");
00136 }
00137 }
00138 }
00139
00140 void
00141 SerialTree::childFromXMLNode(Child &child, void *xmlnode)
00142 {
00143 xmlNode *xnp = (xmlNode *)xmlnode;
00144 if(xnp->type != XML_ELEMENT_NODE)
00145 {
00146 NOT_DONE("brain damage in childFromXMLNode");
00147 return;
00148 }
00149
00150
00151 QString valbuf;
00152 QString lastcmnt;
00153 Child *newkid = NULL;
00154
00155
00156
00157
00158
00159
00160 for(xmlNode *xcp = xnp->childs; xcp; xcp = xcp->next)
00161 {
00162
00163 switch(xcp->type)
00164 {
00165 case XML_COMMENT_NODE:
00166 lastcmnt = (const char *)xmlNodeGetContent(xcp);
00167
00168 break;
00169 case XML_TEXT_NODE:
00170 valbuf += (const char *)xmlNodeGetContent(xcp);
00171
00172 lastcmnt = QString();
00173 break;
00174 case XML_ELEMENT_NODE:
00175
00176 valbuf = QString();
00177
00178 if(!child.tval) child.tval = new SerialTree();
00179
00180 newkid = new Child((const char *)(xcp->name));
00181
00182 child.tval->setComment((const char *)(xcp->name), lastcmnt);
00183 lastcmnt = QString();
00184 childFromXMLNode(*newkid, xcp);
00185 if(newkid->tval) newkid->tval->setSerializableClass(::getSerializableClass(xcp));
00186
00187 child.tval->children.append(newkid);
00188 break;
00189 default:
00190 NOT_DONE("parseXML() doesn't handle node type " << xnp->type);
00191 }
00192 }
00193 if(!child.tval)
00194 {
00195
00196 child.sval = new QString(valbuf);
00197 }
00198 }
00199
00200 }
00201
00202 #endif // HAVE_LIBXML