ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlstorage.cpp
Go to the documentation of this file.
00001 
00002  //
00003  // XML storage C++ classes version 1.3
00004  //
00005  // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007 
00010 
00011 
00012 /*
00013 
00014   All rights reserved.
00015 
00016   Redistribution and use in source and binary forms, with or without
00017   modification, are permitted provided that the following conditions are met:
00018 
00019   * Redistributions of source code must retain the above copyright
00020     notice, this list of conditions and the following disclaimer.
00021   * Redistributions in binary form must reproduce the above copyright
00022     notice, this list of conditions and the following disclaimer in
00023     the documentation and/or other materials provided with the
00024     distribution.
00025 
00026   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036   POSSIBILITY OF SUCH DAMAGE.
00037 
00038 */
00039 
00040 #include <precomp.h>
00041 
00042 #ifndef XS_NO_COMMENT
00043 #define XS_NO_COMMENT   // no #pragma comment(lib, ...) statements in .lib files to enable static linking
00044 #endif
00045 
00046 //#include "xmlstorage.h"
00047 
00048 
00049 namespace XMLStorage {
00050 
00051 
00052  // work around GCC's wide string constant bug
00053 #ifdef __GNUC__
00054 const LPCXSSTR XS_EMPTY = XS_EMPTY_STR;
00055 const LPCXSSTR XS_TRUE = XS_TRUE_STR;
00056 const LPCXSSTR XS_FALSE = XS_FALSE_STR;
00057 const LPCXSSTR XS_INTFMT = XS_INTFMT_STR;
00058 const LPCXSSTR XS_FLOATFMT = XS_FLOATFMT_STR;
00059 #endif
00060 
00061 const XS_String XS_KEY = XS_KEY_STR;
00062 const XS_String XS_VALUE = XS_VALUE_STR;
00063 const XS_String XS_PROPERTY = XS_PROPERTY_STR;
00064 
00065 
00067 static std::string unescape(const char* s, char b, char e)
00068 {
00069     const char* end = s + strlen(s);
00070 
00071 //  if (*s == b)
00072 //      ++s;
00073 //
00074 //  if (end>s && end[-1]==e)
00075 //      --end;
00076 
00077     if (*s == b)
00078         if (end>s && end[-1]==e)
00079             ++s, --end;
00080 
00081     return std::string(s, end-s);
00082 }
00083 
00084 inline std::string unescape(const char* s)
00085 {
00086     return unescape(s, '"', '"');
00087 }
00088 
00090 static std::string unescape(const char* s, size_t l, char b, char e)
00091 {
00092     const char* end = s + l;
00093 
00094 //  if (*s == b)
00095 //      ++s;
00096 //
00097 //  if (end>s && end[-1]==e)
00098 //      --end;
00099 
00100     if (*s == b)
00101         if (end>s && end[-1]==e)
00102             ++s, --end;
00103 
00104     return std::string(s, end-s);
00105 }
00106 
00107 inline std::string unescape(const char* s, size_t l)
00108 {
00109     return unescape(s, l, '"', '"');
00110 }
00111 
00112 
00114 bool XMLPos::go(const XPath& xpath)
00115 {
00116     XMLNode* node = xpath._absolute? _root: _cur;
00117 
00118     node = node->find_relative(xpath);
00119 
00120     if (node) {
00121         go_to(node);
00122         return true;
00123     } else
00124         return false;
00125 }
00126 
00128 bool const_XMLPos::go(const XPath& xpath)
00129 {
00130     const XMLNode* node = xpath._absolute? _root: _cur;
00131 
00132     node = node->find_relative(xpath);
00133 
00134     if (node) {
00135         go_to(node);
00136         return true;
00137     } else
00138         return false;
00139 }
00140 
00141 
00142 const char* XPathElement::parse(const char* path)
00143 {
00144     const char* slash = strchr(path, '/');
00145     if (slash == path)
00146         return NULL;
00147 
00148     size_t l = slash? slash-path: strlen(path);
00149     std::string comp(path, l);
00150     path += l;
00151 
00152      // look for [n] and [@attr_name="attr_value"] expressions in path components
00153     const char* bracket = strchr(comp.c_str(), '[');
00154     l = bracket? bracket-comp.c_str(): comp.length();
00155     _child_name.assign(comp.c_str(), l);
00156 
00157     int n = 0;
00158     if (bracket) {
00159         std::string expr = unescape(bracket, '[', ']');
00160         const char* p = expr.c_str();
00161 
00162         n = atoi(p);    // read index number
00163 
00164         if (n)
00165             _child_idx = n - 1; // convert into zero based index
00166 
00167         const char* at = strchr(p, '@');
00168 
00169         if (at) {
00170             p = at + 1;
00171             const char* equal = strchr(p, '=');
00172 
00173              // read attribute name and value
00174             if (equal) {
00175                 _attr_name = unescape(p, equal-p);
00176                 _attr_value = unescape(equal+1);
00177             }
00178         }
00179     }
00180 
00181     return path;
00182 }
00183 
00184 XMLNode* XPathElement::find(XMLNode* node) const
00185 {
00186     int n = 0;
00187 
00188     for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
00189         if (matches(**it, n))
00190             return *it;
00191 
00192     return NULL;
00193 }
00194 
00195 const XMLNode* XPathElement::const_find(const XMLNode* node) const
00196 {
00197     int n = 0;
00198 
00199     for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
00200         if (matches(**it, n))
00201             return *it;
00202 
00203     return NULL;
00204 }
00205 
00206 bool XPathElement::matches(const XMLNode& node, int& n) const
00207 {
00208     if (node != _child_name)
00209         if (_child_name != XS_TEXT("*"))    // use asterisk as wildcard
00210             return false;
00211 
00212     if (!_attr_name.empty())
00213         if (node.get(_attr_name) != _attr_value)
00214             return false;
00215 
00216     if (_child_idx == -1)
00217         return true;
00218     else if (n++ == _child_idx)
00219         return true;
00220     else
00221         return false;
00222 }
00223 
00224 
00225 void XPath::init(const char* path)
00226 {
00227      // Is this an absolute path?
00228     if (*path == '/') {
00229         _absolute = true;
00230         ++path;
00231     } else
00232         _absolute = false;
00233 
00234      // parse path
00235     while(*path) {
00236         XPathElement elem;
00237 
00238         path = elem.parse(path);
00239 
00240         if (!path)
00241             break;
00242 
00243         if (*path == '/')
00244             ++path;
00245 
00246         push_back(elem);
00247     }
00248 }
00249 
00250 
00251 const XMLNode* XMLNode::find_relative(const XPath& xpath) const
00252 {
00253     const XMLNode* node = this;
00254 
00255     for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
00256         node = it->const_find(node);
00257 
00258         if (!node)
00259             return NULL;
00260     }
00261 
00262     return node;
00263 }
00264 
00265 XMLNode* XMLNode::find_relative(const XPath& xpath)
00266 {
00267     XMLNode* node = this;
00268 
00269     for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
00270         node = it->find(node);
00271 
00272         if (!node)
00273             return NULL;
00274     }
00275 
00276     return node;
00277 }
00278 
00279 XMLNode* XMLNode::create_relative(const XPath& xpath)
00280 {
00281     XMLNode* node = this;
00282 
00283     for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
00284         XMLNode* child = it->find(node);
00285 
00286         if (!child) {
00287             child = new XMLNode(it->_child_name);
00288             node->add_child(child);
00289 
00290             if (!it->_attr_name.empty())
00291                 (*this)[it->_attr_name] = it->_attr_value;
00292         }
00293 
00294         node = child;
00295     }
00296 
00297     return node;
00298 }
00299 
00301 int XMLNode::count(XPath::const_iterator from, const XPath::const_iterator& to) const
00302 {
00303     const XPathElement& elem = *from++;
00304     int cnt = 0;
00305     int n = 0;
00306 
00307     for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00308         if (elem.matches(**it, n)) {
00309             if (from != to)
00310                  // iterate deeper
00311                 cnt += (*it)->count(from, to);
00312             else
00313                  // increment match counter
00314                 ++cnt;
00315         }
00316 
00317     return cnt;
00318 }
00319 
00321 bool XMLNode::filter(const XPath& xpath, XMLNode& target) const
00322 {
00323     XMLNode* ret = filter(xpath.begin(), xpath.end());
00324 
00325     if (ret) {
00326          // move returned nodes to target node
00327         target._children.move(ret->_children);
00328         target._attributes = ret->_attributes;
00329 
00330         delete ret;
00331 
00332         return true;
00333     } else
00334         return false;
00335 }
00336 
00338 XMLNode* XMLNode::filter(XPath::const_iterator from, const XPath::const_iterator& to) const
00339 {
00340     XMLNode* copy = NULL;
00341 
00342     const XPathElement& elem = *from++;
00343     int cnt = 0;
00344     int n = 0;
00345 
00346     for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00347         if (elem.matches(**it, n)) {
00348             if (!copy)
00349                 copy = new XMLNode(*this, XMLNode::COPY_NOCHILDREN);
00350 
00351             if (from != to) {
00352                 XMLNode* ret = (*it)->filter(from, to);
00353 
00354                 if (ret) {
00355                     copy->add_child(ret);
00356                     ++cnt;
00357                 }
00358             } else {
00359                 copy->add_child(new XMLNode(**it, XMLNode::COPY_NOCHILDREN));
00360                 ++cnt;
00361             }
00362         }
00363 
00364     if (cnt > 0) {
00365         return copy;
00366     } else {
00367         delete copy;
00368         return NULL;
00369     }
00370 }
00371 
00372 
00374 std::string EncodeXMLString(const XS_String& str, bool cdata)
00375 {
00376     LPCXSSTR s = str.c_str();
00377     size_t l = XS_len(s);
00378 
00379     if (cdata) {
00380          // encode the whole string in a CDATA section
00381         std::string ret = CDATA_START;
00382 
00383 #ifdef XS_STRING_UTF8
00384         ret += str;
00385 #else
00386         ret += get_utf8(str);
00387 #endif
00388 
00389         ret += CDATA_END;
00390 
00391         return ret;
00392     } else if (l <= BUFFER_LEN) {
00393         LPXSSTR buffer = (LPXSSTR)alloca(6*sizeof(XS_CHAR)*XS_len(s));  // worst case "&quot;" / "&apos;"
00394         LPXSSTR o = buffer;
00395 
00396         for(LPCXSSTR p=s; *p; ++p)
00397             switch(*p) {
00398               case '&':
00399                 *o++ = '&'; *o++ = 'a'; *o++ = 'm'; *o++ = 'p'; *o++ = ';';             // "&amp;"
00400                 break;
00401 
00402               case '<':
00403                 *o++ = '&'; *o++ = 'l'; *o++ = 't'; *o++ = ';';                         // "&lt;"
00404                 break;
00405 
00406               case '>':
00407                 *o++ = '&'; *o++ = 'g'; *o++ = 't'; *o++ = ';';                         // "&gt;"
00408                 break;
00409 
00410               case '"':
00411                 *o++ = '&'; *o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't'; *o++ = ';'; // "&quot;"
00412                 break;
00413 
00414               case '\'':
00415                 *o++ = '&'; *o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's'; *o++ = ';'; // "&apos;"
00416                 break;
00417 
00418               default:
00419                 if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n') {
00420                     char b[16];
00421                     sprintf(b, "&#%d;", (unsigned)*p);
00422                     for(const char*q=b; *q; )
00423                         *o++ = *q++;
00424                 } else
00425                     *o++ = *p;
00426             }
00427 
00428 #ifdef XS_STRING_UTF8
00429         return XS_String(buffer, o-buffer);
00430 #else
00431         return get_utf8(buffer, o-buffer);
00432 #endif
00433     } else { // l > BUFFER_LEN
00434          // alternative code for larger strings using ostringstream
00435          // and avoiding to use alloca() for preallocated memory
00436         fast_ostringstream out;
00437 
00438         LPCXSSTR s = str.c_str();
00439 
00440         for(LPCXSSTR p=s; *p; ++p)
00441             switch(*p) {
00442               case '&':
00443                 out << "&amp;";
00444                 break;
00445 
00446               case '<':
00447                 out << "&lt;";
00448                 break;
00449 
00450               case '>':
00451                 out << "&gt;";
00452                 break;
00453 
00454               case '"':
00455                 out << "&quot;";
00456                 break;
00457 
00458               case '\'':
00459                 out << "&apos;";
00460                 break;
00461 
00462               default:
00463                 if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n')
00464                     out << "&#" << (unsigned)*p << ";";
00465                 else
00466                     out << *p;
00467             }
00468 
00469 #ifdef XS_STRING_UTF8
00470         return XS_String(out.str());
00471 #else
00472         return get_utf8(out.str());
00473 #endif
00474     }
00475 }
00476 
00478 XS_String DecodeXMLString(const std::string& str)
00479 {
00480 #ifdef XS_STRING_UTF8
00481     const XS_String& str_utf8 = str;
00482 #else
00483     XS_String str_utf8;
00484     assign_utf8(str_utf8, str.c_str(), str.length());
00485 #endif
00486 
00487     LPCXSSTR s = str_utf8.c_str();
00488     LPXSSTR buffer = (LPXSSTR)alloca(sizeof(XS_CHAR)*XS_len(s));
00489     LPXSSTR o = buffer;
00490 
00491     for(LPCXSSTR p=s; *p; ++p)
00492         if (*p == '&') {
00493             if (!XS_nicmp(p+1, XS_TEXT("lt;"), 3)) {
00494                 *o++ = '<';
00495                 p += 3;
00496             } else if (!XS_nicmp(p+1, XS_TEXT("gt;"), 3)) {
00497                 *o++ = '>';
00498                 p += 3;
00499             } else if (!XS_nicmp(p+1, XS_TEXT("amp;"), 4)) {
00500                 *o++ = '&';
00501                 p += 4;
00502             } else if (!XS_nicmp(p+1, XS_TEXT("quot;"), 5)) {
00503                 *o++ = '"';
00504                 p += 5;
00505             } else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) {
00506                 *o++ = '\'';
00507                 p += 5;
00508             } else  //@@ maybe decode "&#xx;" special characters
00509                 *o++ = *p;
00510         } else if (*p=='<' && !XS_nicmp(p+1,XS_TEXT("![CDATA["),8)) {
00511             LPCXSSTR e = XS_strstr(p+9, XS_TEXT(CDATA_END));
00512             if (e) {
00513                 p += 9;
00514                 size_t l = e - p;
00515                 memcpy(o, p, l);
00516                 o += l;
00517                 p = e + 2;
00518             } else
00519                 *o++ = *p;
00520         } else
00521             *o++ = *p;
00522 
00523     return XS_String(buffer, o-buffer);
00524 }
00525 
00526 
00528 void XMLNode::original_write_worker(std::ostream& out) const
00529 {
00530     out << _leading << '<' << EncodeXMLString(*this);
00531 
00532     for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
00533         out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
00534 
00535     if (!_children.empty() || !_content.empty()) {
00536         out << '>';
00537 
00538         if (_cdata_content)
00539             out << CDATA_START << _content << CDATA_END;
00540         else
00541             out << _content;
00542 
00543         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00544             (*it)->original_write_worker(out);
00545 
00546         out << _end_leading << "</" << EncodeXMLString(*this) << '>';
00547     } else
00548         out << "/>";
00549 
00550     out << _trailing;
00551 }
00552 
00553 
00555 void XMLNode::plain_write_worker(std::ostream& out) const
00556 {
00557     out << '<' << EncodeXMLString(*this);
00558 
00559     for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
00560         out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
00561 
00562      // strip leading white space from content
00563     const char* content = _content.c_str();
00564     while(isspace((unsigned char)*content)) ++content;
00565 
00566     if (!_children.empty() || *content) {
00567         out << ">" << content;
00568 
00569         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00570             (*it)->plain_write_worker(out);
00571 
00572         out << "</" << EncodeXMLString(*this) << ">";
00573     } else
00574         out << "/>";
00575 }
00576 
00577 
00579 void XMLNode::pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const
00580 {
00581     for(int i=indent; i--; )
00582         out << XML_INDENT_SPACE;
00583 
00584     out << '<' << EncodeXMLString(*this);
00585 
00586     for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
00587         out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
00588 
00589      // strip leading white space from content
00590     const char* content = _content.c_str();
00591     while(isspace((unsigned char)*content)) ++content;
00592 
00593     if (!_children.empty() || *content) {
00594         out << '>' << content;
00595 
00596         if (!_children.empty())
00597             out << format._endl;
00598 
00599         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00600             (*it)->pretty_write_worker(out, format, indent+1);
00601 
00602         for(int i=indent; i--; )
00603             out << XML_INDENT_SPACE;
00604 
00605         out << "</" << EncodeXMLString(*this) << '>' << format._endl;
00606     } else
00607         out << "/>" << format._endl;
00608 }
00609 
00610 
00612 void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const
00613 {
00614      // strip the first line feed from _leading
00615     const char* leading = _leading.c_str();
00616     if (*leading == '\n') ++leading;
00617 
00618     if (!*leading)
00619         for(int i=indent; i--; )
00620             out << XML_INDENT_SPACE;
00621     else
00622         out << leading;
00623 
00624     out << '<' << EncodeXMLString(*this);
00625 
00626     for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
00627         out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
00628 
00629      // strip leading white space from content
00630     const char* content = _content.c_str();
00631     while(isspace((unsigned char)*content)) ++content;
00632 
00633     if (_children.empty() && !*content)
00634         out << "/>";
00635     else {
00636         out << '>';
00637 
00638         if (_cdata_content)
00639             out << CDATA_START << _content << CDATA_END;
00640         else if (!*content)
00641             out << format._endl;
00642         else
00643             out << content;
00644 
00645         Children::const_iterator it = _children.begin();
00646 
00647         if (it != _children.end()) {
00648             for(; it!=_children.end(); ++it)
00649                 (*it)->smart_write_worker(out, format, indent+1);
00650 
00651              // strip the first line feed from _end_leading
00652             const char* end_leading = _end_leading.c_str();
00653             if (*end_leading == '\n') ++end_leading;
00654 
00655             if (!*end_leading)
00656                 for(int i=indent; i--; )
00657                     out << XML_INDENT_SPACE;
00658             else
00659                 out << end_leading;
00660         } else
00661             out << _end_leading;
00662 
00663         out << "</" << EncodeXMLString(*this) << '>';
00664     }
00665 
00666     if (_trailing.empty())
00667         out << format._endl;
00668     else
00669         out << _trailing;
00670 }
00671 
00672 
00673 std::ostream& operator<<(std::ostream& out, const XMLError& err)
00674 {
00675     out << err._systemId << "(" << err._line << ") [column " << err._column << "] : "
00676         << err._message;
00677 
00678     return out;
00679 }
00680 
00681 
00682 const char* get_xmlsym_end_utf8(const char* p)
00683 {
00684     for(; *p; ++p) {
00685         char c = *p;
00686 
00687         // NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
00688         if (c == '\xC3')    // UTF-8 escape character
00689             ++p;    //TODO only continue on umlaut characters
00690         else if (!isalnum(c) && c!='.' && c!='-' && c!='_' && c!=':')
00691             break;
00692     }
00693 
00694     return p;
00695 }
00696 
00697 
00698 void DocType::parse(const char* p)
00699 {
00700     while(isspace((unsigned char)*p)) ++p;
00701 
00702     const char* start = p;
00703     p = get_xmlsym_end_utf8(p);
00704     _name.assign(start, p-start);
00705 
00706     while(isspace((unsigned char)*p)) ++p;
00707 
00708     start = p;
00709     p = get_xmlsym_end_utf8(p);
00710     std::string keyword(p, p-start);    // "PUBLIC" or "SYSTEM"
00711 
00712     while(isspace((unsigned char)*p)) ++p;
00713 
00714     if (*p=='"' || *p=='\'') {
00715         char delim = *p;
00716 
00717         start = ++p;
00718         while(*p && *p!=delim) ++p;
00719 
00720         if (*p == delim)
00721             _public.assign(start, p++-start);
00722     } else
00723         _public.erase();
00724 
00725     while(isspace((unsigned char)*p)) ++p;
00726 
00727     if (*p=='"' || *p=='\'') {
00728         char delim = *p;
00729 
00730         start = ++p;
00731         while(*p && *p!=delim) ++p;
00732 
00733         if (*p == delim)
00734             _system.assign(start, p++-start);
00735     } else
00736         _system.erase();
00737 }
00738 
00739 
00740 void XMLFormat::print_header(std::ostream& out, bool lf) const
00741 {
00742     out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"";
00743 
00744     if (_standalone != -1)
00745         out << " standalone=\"yes\"";
00746 
00747     out << "?>";
00748 
00749     if (lf)
00750         out << _endl;
00751 
00752     if (!_doctype.empty()) {
00753         out << "<!DOCTYPE " << _doctype._name;
00754 
00755         if (!_doctype._public.empty()) {
00756             out << " PUBLIC \"" << _doctype._public << '"';
00757 
00758             if (lf)
00759                 out << _endl;
00760 
00761             out << " \"" << _doctype._system << '"';
00762         } else if (!_doctype._system.empty())
00763             out << " SYSTEM \"" << _doctype._system << '"';
00764 
00765         out << "?>";
00766 
00767         if (lf)
00768             out << _endl;
00769     }
00770 
00771     for(StyleSheetList::const_iterator it=_stylesheets.begin(); it!=_stylesheets.end(); ++it) {
00772         it->print(out);
00773 
00774         if (lf)
00775             out << _endl;
00776     }
00777 
00778 /*  if (!_additional.empty()) {
00779         out << _additional;
00780 
00781         if (lf)
00782             out << _endl;
00783     } */
00784 }
00785 
00786 void StyleSheet::print(std::ostream& out) const
00787 {
00788     out << "<?xml-stylesheet"
00789             " href=\"" << _href << "\""
00790             " type=\"" << _type << "\"";
00791 
00792     if (!_title.empty())
00793         out << " title=\"" << _title << "\"";
00794 
00795     if (!_media.empty())
00796         out << " media=\"" << _media << "\"";
00797 
00798     if (!_charset.empty())
00799         out << " charset=\"" << _charset << "\"";
00800 
00801     if (_alternate)
00802         out << " alternate=\"yes\"";
00803 
00804     out << "?>";
00805 }
00806 
00807 
00809 std::string XMLError::str() const
00810 {
00811     std::ostringstream out;
00812 
00813     out << *this;
00814 
00815     return out.str();
00816 }
00817 
00818 
00820 XS_String XMLErrorList::str() const
00821 {
00822     std::ostringstream out;
00823 
00824     for(const_iterator it=begin(); it!=end(); ++it)
00825         out << *it << std::endl;
00826 
00827     return out.str();
00828 }
00829 
00830 
00831 void XMLReaderBase::finish_read()
00832 {
00833     if (_pos->_children.empty())
00834         _pos->_trailing.append(_content);
00835     else
00836         _pos->_children.back()->_trailing.append(_content);
00837 
00838     _content.erase();
00839 }
00840 
00841 
00843 void XMLReaderBase::XmlDeclHandler(const char* version, const char* encoding, int standalone)
00844 {
00845     if (version)
00846         _format._version = version;
00847 
00848     if (encoding)
00849         _format._encoding = encoding;
00850 
00851     _format._standalone = standalone;
00852 }
00853 
00854 
00856 void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes)
00857 {
00858     const char* s = _content.c_str();
00859     const char* e = s + _content.length();
00860     const char* p = s;
00861 
00862      // search for content end leaving only white space for leading
00863     for(p=e; p>s; --p)
00864         if (!isspace((unsigned char)p[-1]))
00865             break;
00866 
00867     if (p != s) {
00868         if (_pos->_children.empty()) {  // no children in last node?
00869             if (_last_tag == TAG_START)
00870                 _pos->_content.append(s, p-s);
00871             else if (_last_tag == TAG_END)
00872                 _pos->_trailing.append(s, p-s);
00873             else // TAG_NONE at root node
00874                 p = s;
00875         } else
00876             _pos->_children.back()->_trailing.append(s, p-s);
00877     }
00878 
00879     std::string leading;
00880 
00881     if (p != e)
00882         leading.assign(p, e-p);
00883 
00884     XMLNode* node = new XMLNode(name, leading);
00885 
00886     _pos.add_down(node);
00887 
00888 #ifdef XMLNODE_LOCATION
00889     node->_location = get_location();
00890 #endif
00891 
00892     node->_attributes = attributes;
00893 
00894     _last_tag = TAG_START;
00895     _content.erase();
00896 }
00897 
00899 void XMLReaderBase::EndElementHandler()
00900 {
00901     const char* s = _content.c_str();
00902     const char* e = s + _content.length();
00903     const char* p;
00904 
00905     if (!strncmp(s,CDATA_START,9) && !strncmp(e-3,CDATA_END,3)) {
00906         s += 9;
00907         p = (e-=3);
00908 
00909         _pos->_cdata_content = true;
00910     } else {
00911          // search for content end leaving only white space for _end_leading
00912         for(p=e; p>s; --p)
00913             if (!isspace((unsigned char)p[-1]))
00914                 break;
00915 
00916         _pos->_cdata_content = false;
00917     }
00918 
00919     if (p != s) {
00920         if (_pos->_children.empty())    // no children in current node?
00921             _pos->_content.append(s, p-s);
00922         else if (_last_tag == TAG_START)
00923             _pos->_content.append(s, p-s);
00924         else
00925             _pos->_children.back()->_trailing.append(s, p-s);
00926     }
00927 
00928     if (p != e)
00929         _pos->_end_leading.assign(p, e-p);
00930 
00931     _pos.back();
00932 
00933     _last_tag = TAG_END;
00934     _content.erase();
00935 }
00936 
00937 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
00938 
00939 void XMLReaderBase::DefaultHandler(const XML_Char* s, int len)
00940 {
00941 #if defined(XML_UNICODE) || defined(XS_USE_XERCES)
00942     _content.append(String_from_XML_Char(s, len));
00943 #else
00944     _content.append(s, len);
00945 #endif
00946 }
00947 #endif
00948 
00949 
00950 XS_String XMLWriter::s_empty_attr;
00951 
00952 void XMLWriter::create(const XS_String& name)
00953 {
00954     if (!_stack.empty()) {
00955         StackEntry& last = _stack.top();
00956 
00957         if (last._state < PRE_CLOSED) {
00958             write_attributes(last);
00959             close_pre(last);
00960         }
00961 
00962         ++last._children;
00963     }
00964 
00965     StackEntry entry;
00966     entry._node_name = name;
00967     _stack.push(entry);
00968 
00969     write_pre(entry);
00970 }
00971 
00972 bool XMLWriter::back()
00973 {
00974     if (!_stack.empty()) {
00975         write_post(_stack.top());
00976 
00977         _stack.pop();
00978         return true;
00979     } else
00980         return false;
00981 }
00982 
00983 void XMLWriter::close_pre(StackEntry& entry)
00984 {
00985     _out << '>';
00986 
00987     entry._state = PRE_CLOSED;
00988 }
00989 
00990 void XMLWriter::write_pre(StackEntry& entry)
00991 {
00992     if (_format._pretty >= PRETTY_LINEFEED)
00993         _out << _format._endl;
00994 
00995     if (_format._pretty == PRETTY_INDENT) {
00996         for(size_t i=_stack.size(); --i>0; )
00997             _out << XML_INDENT_SPACE;
00998     }
00999 
01000     _out << '<' << EncodeXMLString(entry._node_name);
01001     //entry._state = PRE;
01002 }
01003 
01004 void XMLWriter::write_attributes(StackEntry& entry)
01005 {
01006     for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it)
01007         _out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
01008 
01009     entry._state = ATTRIBUTES;
01010 }
01011 
01012 void XMLWriter::write_post(StackEntry& entry)
01013 {
01014     if (entry._state < ATTRIBUTES)
01015         write_attributes(entry);
01016 
01017     if (entry._children || !entry._content.empty()) {
01018         if (entry._state < PRE_CLOSED)
01019             close_pre(entry);
01020 
01021         _out << entry._content;
01022         //entry._state = CONTENT;
01023 
01024         if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
01025             _out << _format._endl;
01026 
01027         if (_format._pretty==PRETTY_INDENT && entry._content.empty()) {
01028             for(size_t i=_stack.size(); --i>0; )
01029                 _out << XML_INDENT_SPACE;
01030         }
01031 
01032         _out << "</" << EncodeXMLString(entry._node_name) << ">";
01033     } else {
01034         _out << "/>";
01035     }
01036 
01037     entry._state = POST;
01038 }
01039 
01040 
01041 }   // namespace XMLStorage

Generated on Sat May 26 2012 04:17:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.