version 0.3.0
[fms.git] / include / ifmsxmldocument.h
index ae555a1..6358e8f 100644 (file)
@@ -1,10 +1,18 @@
 #ifndef _ifmsxmldocument_\r
 #define _ifmsxmldocument_\r
 \r
+#include <Poco/DOM/Document.h>\r
+#include <Poco/DOM/Element.h>\r
+#include <Poco/DOM/Text.h>\r
+#include <Poco/DOM/CDATASection.h>\r
+#include <Poco/DOM/DOMParser.h>\r
+#include <Poco/DOM/DOMWriter.h>\r
+#include <Poco/XML/XMLWriter.h>\r
+#include <Poco/AutoPtr.h>\r
+\r
 #include "stringfunctions.h"\r
 \r
 #include <string>\r
-#include <tinyxml.h>\r
 \r
 #ifdef XMEM\r
        #include <xmem.h>\r
@@ -33,53 +41,116 @@ public:
 \r
 protected:\r
        /**\r
+               Poco doesn't like CDATA with whitespace outside the tags\r
+               This will remove the whitespace from around CDATA tags\r
+       */\r
+       virtual const std::string FixCDATA(const std::string &xmlstr)\r
+       {\r
+               std::string rstring=xmlstr;\r
+               std::string::size_type beg1=std::string::npos;\r
+               std::string::size_type end1=rstring.find("<![CDATA[");\r
+               std::string::size_type beg2=std::string::npos;\r
+               std::string::size_type end2=std::string::npos;\r
+\r
+               while(end1!=std::string::npos)\r
+               {\r
+                       beg1=rstring.rfind(">",end1);\r
+                       if(beg1!=end1-1)\r
+                       {\r
+                               rstring.erase(beg1+1,end1-(beg1+1));\r
+                       }\r
+\r
+                       beg2=rstring.find("]]>",end1);\r
+                       if(beg2!=std::string::npos)\r
+                       {\r
+                               end2=rstring.find("<",beg2);\r
+                               if(end2!=std::string::npos)\r
+                               {\r
+                                       rstring.erase(beg2+3,end2-(beg2+3));\r
+                               }\r
+                       }\r
+\r
+                       end1=rstring.find("<![CDATA[",end1+1);\r
+               }\r
+               return rstring;\r
+       }\r
+       /**\r
                \brief Creates and returns an element with a boolean value\r
        */\r
-       virtual TiXmlElement *XMLCreateBooleanElement(const std::string &name, const bool value)\r
+       virtual Poco::XML::Element *XMLCreateBooleanElement(Poco::XML::Document *doc, const std::string &name, const bool value)\r
        {\r
-               TiXmlText *txt=new TiXmlText(value ? "true" : "false");\r
-               TiXmlElement *el=new TiXmlElement(name);\r
-               el->LinkEndChild(txt);\r
-               return el;\r
+               if(doc)\r
+               {\r
+                       Poco::XML::Text *txt=doc->createTextNode(value ? "true" : "false");\r
+                       Poco::XML::Element *el=doc->createElement(name);\r
+                       el->appendChild(txt);\r
+                       return el;\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
        }\r
 \r
        /**\r
                \brief Creates and returns an element with a CDATA value\r
        */\r
-       virtual TiXmlElement *XMLCreateCDATAElement(const std::string &name, const std::string &data)\r
+       virtual Poco::XML::Element *XMLCreateCDATAElement(Poco::XML::Document *doc, const std::string &name, const std::string &data)\r
        {\r
-               TiXmlText *txt=new TiXmlText(data);\r
-               txt->SetCDATA(true);\r
-               TiXmlElement *el=new TiXmlElement(name);\r
-               el->LinkEndChild(txt);\r
-               return el;\r
+               if(doc)\r
+               {\r
+                       // Poco XML won't break up CDATA sections correctly when assigned a string with the \r
+                       // end tag is present.  However, it will parse it correctly, so we will manually break the\r
+                       // CDATA into separate parts\r
+                       Poco::XML::CDATASection *sec=doc->createCDATASection(StringFunctions::Replace(data,"]]>","]]]><![CDATA[]>"));\r
+                       Poco::XML::Element *el=doc->createElement(name);\r
+                       el->appendChild(sec);\r
+                       return el;\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
        }\r
 \r
        /**\r
                \brief Creates and returns a text element\r
        */\r
-       virtual TiXmlElement *XMLCreateTextElement(const std::string &name, const std::string &data)\r
+       virtual Poco::XML::Element *XMLCreateTextElement(Poco::XML::Document *doc, const std::string &name, const std::string &data)\r
        {\r
-               TiXmlText *txt=new TiXmlText(data);\r
-               TiXmlElement *el=new TiXmlElement(name);\r
-               el->LinkEndChild(txt);\r
-               return el;\r
+               if(doc)\r
+               {\r
+                       Poco::XML::Text *txt=doc->createTextNode(data);\r
+                       Poco::XML::Element *el=doc->createElement(name);\r
+                       el->appendChild(txt);\r
+                       return el;\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
        }\r
 \r
-       virtual TiXmlElement *XMLCreateTextElement(const std::string &name, const long data)\r
+       virtual Poco::XML::Element *XMLCreateTextElement(Poco::XML::Document *doc, const std::string &name, const long data)\r
        {\r
-               std::string datastr;\r
-               StringFunctions::Convert(data,datastr);\r
-               return XMLCreateTextElement(name,datastr);\r
+               if(doc)\r
+               {\r
+                       std::string datastr;\r
+                       StringFunctions::Convert(data,datastr);\r
+                       return XMLCreateTextElement(doc,name,datastr);\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
        }\r
 \r
-       virtual const bool XMLGetBooleanElement(TiXmlElement *parent, const std::string &name)\r
+       virtual const bool XMLGetBooleanElement(Poco::XML::Element *parent, const std::string &name)\r
        {\r
-               TiXmlHandle hnd(parent);\r
-               TiXmlText *txt=hnd.FirstChild(name).FirstChild().ToText();\r
-               if(txt)\r
+               Poco::XML::Element *el=XMLGetFirstChild(parent,name);\r
+               if(el && el->firstChild())\r
                {\r
-                       if(txt->ValueStr()=="true")\r
+                       if(el->firstChild()->getNodeValue()=="true")\r
                        {\r
                                return true;\r
                        }\r
@@ -91,6 +162,40 @@ protected:
                return false;\r
        }\r
 \r
+       virtual Poco::XML::Element *XMLGetFirstChild(Poco::XML::Node *parent, const std::string &name)\r
+       {\r
+               if(parent)\r
+               {\r
+                       Poco::XML::Node *child=parent->firstChild();\r
+                       while(child && child->nodeName()!=name)\r
+                       {\r
+                               child=child->nextSibling();\r
+                       }\r
+                       return static_cast<Poco::XML::Element *>(child);\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       virtual Poco::XML::Element *XMLGetNextSibling(Poco::XML::Node *node, const std::string &name)\r
+       {\r
+               if(node)\r
+               {\r
+                       Poco::XML::Node *next=node->nextSibling();\r
+                       while(next && next->nodeName()!=name)\r
+                       {\r
+                               next=next->nextSibling();\r
+                       }\r
+                       return static_cast<Poco::XML::Element *>(next);\r
+               }\r
+               else\r
+               {\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
        const std::string SanitizeSingleString(const std::string &text)\r
        {\r
                std::string returntext=text;\r
@@ -101,6 +206,19 @@ protected:
                }\r
                return returntext;\r
        }\r
+\r
+       const std::string GenerateXML(Poco::XML::Document *doc)\r
+       {\r
+               std::ostringstream str;\r
+               if(doc)\r
+               {\r
+                       Poco::XML::DOMWriter dr;\r
+                       dr.setOptions(Poco::XML::XMLWriter::WRITE_XML_DECLARATION | Poco::XML::XMLWriter::PRETTY_PRINT);\r
+                       dr.setNewLine(Poco::XML::XMLWriter::NEWLINE_CRLF);\r
+                       dr.writeNode(str,doc);\r
+               }\r
+               return str.str();\r
+       }\r
        \r
 };\r
 \r