ReactOS  0.4.11-dev-745-g76daaf9
xmlstorage.cpp
Go to the documentation of this file.
1 
2  //
3  // XML storage C++ classes version 1.3
4  //
5  // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Martin Fuchs <martin-fuchs@gmx.net>
6  //
7 
10 
11 
12 /*
13 
14  All rights reserved.
15 
16  Redistribution and use in source and binary forms, with or without
17  modification, are permitted provided that the following conditions are met:
18 
19  * Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21  * Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in
23  the documentation and/or other materials provided with the
24  distribution.
25 
26  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  POSSIBILITY OF SUCH DAMAGE.
37 
38 */
39 
40 #include <precomp.h>
41 
42 #ifndef XS_NO_COMMENT
43 #define XS_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files to enable static linking
44 #endif
45 
46 //#include "xmlstorage.h"
47 
48 
49 namespace XMLStorage {
50 
51 
52  // work around GCC's wide string constant bug
53 #ifdef __GNUC__
59 #endif
60 
64 
65 
67 static std::string unescape(const char* s, char b, char e)
68 {
69  const char* end = s + strlen(s);
70 
71 // if (*s == b)
72 // ++s;
73 //
74 // if (end>s && end[-1]==e)
75 // --end;
76 
77  if (*s == b)
78  if (end>s && end[-1]==e)
79  ++s, --end;
80 
81  return std::string(s, end-s);
82 }
83 
84 inline std::string unescape(const char* s)
85 {
86  return unescape(s, '"', '"');
87 }
88 
90 static std::string unescape(const char* s, size_t l, char b, char e)
91 {
92  const char* end = s + l;
93 
94 // if (*s == b)
95 // ++s;
96 //
97 // if (end>s && end[-1]==e)
98 // --end;
99 
100  if (*s == b)
101  if (end>s && end[-1]==e)
102  ++s, --end;
103 
104  return std::string(s, end-s);
105 }
106 
107 inline std::string unescape(const char* s, size_t l)
108 {
109  return unescape(s, l, '"', '"');
110 }
111 
112 
114 bool XMLPos::go(const XPath& xpath)
115 {
116  XMLNode* node = xpath._absolute? _root: _cur;
117 
118  node = node->find_relative(xpath);
119 
120  if (node) {
121  go_to(node);
122  return true;
123  } else
124  return false;
125 }
126 
128 bool const_XMLPos::go(const XPath& xpath)
129 {
130  const XMLNode* node = xpath._absolute? _root: _cur;
131 
132  node = node->find_relative(xpath);
133 
134  if (node) {
135  go_to(node);
136  return true;
137  } else
138  return false;
139 }
140 
141 
142 const char* XPathElement::parse(const char* path)
143 {
144  const char* slash = strchr(path, '/');
145  if (slash == path)
146  return NULL;
147 
148  size_t l = slash? slash-path: strlen(path);
149  std::string comp(path, l);
150  path += l;
151 
152  // look for [n] and [@attr_name="attr_value"] expressions in path components
153  const char* bracket = strchr(comp.c_str(), '[');
154  l = bracket? bracket-comp.c_str(): comp.length();
155  _child_name.assign(comp.c_str(), l);
156 
157  int n = 0;
158  if (bracket) {
159  std::string expr = unescape(bracket, '[', ']');
160  const char* p = expr.c_str();
161 
162  n = atoi(p); // read index number
163 
164  if (n)
165  _child_idx = n - 1; // convert into zero based index
166 
167  const char* at = strchr(p, '@');
168 
169  if (at) {
170  p = at + 1;
171  const char* equal = strchr(p, '=');
172 
173  // read attribute name and value
174  if (equal) {
175  _attr_name = unescape(p, equal-p);
176  _attr_value = unescape(equal+1);
177  }
178  }
179  }
180 
181  return path;
182 }
183 
185 {
186  int n = 0;
187 
188  for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
189  if (matches(**it, n))
190  return *it;
191 
192  return NULL;
193 }
194 
196 {
197  int n = 0;
198 
199  for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
200  if (matches(**it, n))
201  return *it;
202 
203  return NULL;
204 }
205 
206 bool XPathElement::matches(const XMLNode& node, int& n) const
207 {
208  if (node != _child_name)
209  if (_child_name != XS_TEXT("*")) // use asterisk as wildcard
210  return false;
211 
212  if (!_attr_name.empty())
213  if (node.get(_attr_name) != _attr_value)
214  return false;
215 
216  if (_child_idx == -1)
217  return true;
218  else if (n++ == _child_idx)
219  return true;
220  else
221  return false;
222 }
223 
224 
225 void XPath::init(const char* path)
226 {
227  // Is this an absolute path?
228  if (*path == '/') {
229  _absolute = true;
230  ++path;
231  } else
232  _absolute = false;
233 
234  // parse path
235  while(*path) {
237 
238  path = elem.parse(path);
239 
240  if (!path)
241  break;
242 
243  if (*path == '/')
244  ++path;
245 
246  push_back(elem);
247  }
248 }
249 
250 
251 const XMLNode* XMLNode::find_relative(const XPath& xpath) const
252 {
253  const XMLNode* node = this;
254 
255  for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
256  node = it->const_find(node);
257 
258  if (!node)
259  return NULL;
260  }
261 
262  return node;
263 }
264 
266 {
267  XMLNode* node = this;
268 
269  for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
270  node = it->find(node);
271 
272  if (!node)
273  return NULL;
274  }
275 
276  return node;
277 }
278 
280 {
281  XMLNode* node = this;
282 
283  for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
284  XMLNode* child = it->find(node);
285 
286  if (!child) {
287  child = new XMLNode(it->_child_name);
288  node->add_child(child);
289 
290  if (!it->_attr_name.empty())
291  (*this)[it->_attr_name] = it->_attr_value;
292  }
293 
294  node = child;
295  }
296 
297  return node;
298 }
299 
301 int XMLNode::count(XPath::const_iterator from, const XPath::const_iterator& to) const
302 {
303  const XPathElement& elem = *from++;
304  int cnt = 0;
305  int n = 0;
306 
307  for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
308  if (elem.matches(**it, n)) {
309  if (from != to)
310  // iterate deeper
311  cnt += (*it)->count(from, to);
312  else
313  // increment match counter
314  ++cnt;
315  }
316 
317  return cnt;
318 }
319 
321 bool XMLNode::filter(const XPath& xpath, XMLNode& target) const
322 {
323  XMLNode* ret = filter(xpath.begin(), xpath.end());
324 
325  if (ret) {
326  // move returned nodes to target node
327  target._children.move(ret->_children);
328  target._attributes = ret->_attributes;
329 
330  delete ret;
331 
332  return true;
333  } else
334  return false;
335 }
336 
338 XMLNode* XMLNode::filter(XPath::const_iterator from, const XPath::const_iterator& to) const
339 {
340  XMLNode* copy = NULL;
341 
342  const XPathElement& elem = *from++;
343  int cnt = 0;
344  int n = 0;
345 
346  for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
347  if (elem.matches(**it, n)) {
348  if (!copy)
349  copy = new XMLNode(*this, XMLNode::COPY_NOCHILDREN);
350 
351  if (from != to) {
352  XMLNode* ret = (*it)->filter(from, to);
353 
354  if (ret) {
355  copy->add_child(ret);
356  ++cnt;
357  }
358  } else {
359  copy->add_child(new XMLNode(**it, XMLNode::COPY_NOCHILDREN));
360  ++cnt;
361  }
362  }
363 
364  if (cnt > 0) {
365  return copy;
366  } else {
367  delete copy;
368  return NULL;
369  }
370 }
371 
372 
375 {
376  LPCXSSTR s = str.c_str();
377  size_t l = XS_len(s);
378 
379  if (cdata) {
380  // encode the whole string in a CDATA section
382 
383 #ifdef XS_STRING_UTF8
384  ret += str;
385 #else
386  ret += get_utf8(str);
387 #endif
388 
389  ret += CDATA_END;
390 
391  return ret;
392  } else if (l <= BUFFER_LEN) {
393  LPXSSTR buffer = (LPXSSTR)alloca(6*sizeof(XS_CHAR)*XS_len(s)); // worst case "&quot;" / "&apos;"
394  LPXSSTR o = buffer;
395 
396  for(LPCXSSTR p=s; *p; ++p)
397  switch(*p) {
398  case '&':
399  *o++ = '&'; *o++ = 'a'; *o++ = 'm'; *o++ = 'p'; *o++ = ';'; // "&amp;"
400  break;
401 
402  case '<':
403  *o++ = '&'; *o++ = 'l'; *o++ = 't'; *o++ = ';'; // "&lt;"
404  break;
405 
406  case '>':
407  *o++ = '&'; *o++ = 'g'; *o++ = 't'; *o++ = ';'; // "&gt;"
408  break;
409 
410  case '"':
411  *o++ = '&'; *o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't'; *o++ = ';'; // "&quot;"
412  break;
413 
414  case '\'':
415  *o++ = '&'; *o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's'; *o++ = ';'; // "&apos;"
416  break;
417 
418  default:
419  if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n') {
420  char b[16];
421  sprintf(b, "&#%d;", (unsigned)*p);
422  for(const char*q=b; *q; )
423  *o++ = *q++;
424  } else
425  *o++ = *p;
426  }
427 
428 #ifdef XS_STRING_UTF8
429  return XS_String(buffer, o-buffer);
430 #else
431  return get_utf8(buffer, o-buffer);
432 #endif
433  } else { // l > BUFFER_LEN
434  // alternative code for larger strings using ostringstream
435  // and avoiding to use alloca() for preallocated memory
437 
438  LPCXSSTR s = str.c_str();
439 
440  for(LPCXSSTR p=s; *p; ++p)
441  switch(*p) {
442  case '&':
443  out << "&amp;";
444  break;
445 
446  case '<':
447  out << "&lt;";
448  break;
449 
450  case '>':
451  out << "&gt;";
452  break;
453 
454  case '"':
455  out << "&quot;";
456  break;
457 
458  case '\'':
459  out << "&apos;";
460  break;
461 
462  default:
463  if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n')
464  out << "&#" << (unsigned)*p << ";";
465  else
466  out << *p;
467  }
468 
469 #ifdef XS_STRING_UTF8
470  return XS_String(out.str());
471 #else
472  return get_utf8(out.str());
473 #endif
474  }
475 }
476 
479 {
480 #ifdef XS_STRING_UTF8
481  const XS_String& str_utf8 = str;
482 #else
483  XS_String str_utf8;
484  assign_utf8(str_utf8, str.c_str(), str.length());
485 #endif
486 
487  LPCXSSTR s = str_utf8.c_str();
488  LPXSSTR buffer = (LPXSSTR)alloca(sizeof(XS_CHAR)*XS_len(s));
489  LPXSSTR o = buffer;
490 
491  for(LPCXSSTR p=s; *p; ++p)
492  if (*p == '&') {
493  if (!XS_nicmp(p+1, XS_TEXT("lt;"), 3)) {
494  *o++ = '<';
495  p += 3;
496  } else if (!XS_nicmp(p+1, XS_TEXT("gt;"), 3)) {
497  *o++ = '>';
498  p += 3;
499  } else if (!XS_nicmp(p+1, XS_TEXT("amp;"), 4)) {
500  *o++ = '&';
501  p += 4;
502  } else if (!XS_nicmp(p+1, XS_TEXT("quot;"), 5)) {
503  *o++ = '"';
504  p += 5;
505  } else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) {
506  *o++ = '\'';
507  p += 5;
508  } else //@@ maybe decode "&#xx;" special characters
509  *o++ = *p;
510  } else if (*p=='<' && !XS_nicmp(p+1,XS_TEXT("![CDATA["),8)) {
512  if (e) {
513  p += 9;
514  size_t l = e - p;
515  memcpy(o, p, l);
516  o += l;
517  p = e + 2;
518  } else
519  *o++ = *p;
520  } else
521  *o++ = *p;
522 
523  return XS_String(buffer, o-buffer);
524 }
525 
526 
529 {
530  out << _leading << '<' << EncodeXMLString(*this);
531 
532  for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
533  out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
534 
535  if (!_children.empty() || !_content.empty()) {
536  out << '>';
537 
538  if (_cdata_content)
539  out << CDATA_START << _content << CDATA_END;
540  else
541  out << _content;
542 
543  for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
544  (*it)->original_write_worker(out);
545 
546  out << _end_leading << "</" << EncodeXMLString(*this) << '>';
547  } else
548  out << "/>";
549 
550  out << _trailing;
551 }
552 
553 
555 void XMLNode::plain_write_worker(std::ostream& out) const
556 {
557  out << '<' << EncodeXMLString(*this);
558 
559  for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
560  out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
561 
562  // strip leading white space from content
563  const char* content = _content.c_str();
564  while(isspace((unsigned char)*content)) ++content;
565 
566  if (!_children.empty() || *content) {
567  out << ">" << content;
568 
569  for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
570  (*it)->plain_write_worker(out);
571 
572  out << "</" << EncodeXMLString(*this) << ">";
573  } else
574  out << "/>";
575 }
576 
577 
579 void XMLNode::pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const
580 {
581  for(int i=indent; i--; )
582  out << XML_INDENT_SPACE;
583 
584  out << '<' << EncodeXMLString(*this);
585 
586  for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
587  out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
588 
589  // strip leading white space from content
590  const char* content = _content.c_str();
591  while(isspace((unsigned char)*content)) ++content;
592 
593  if (!_children.empty() || *content) {
594  out << '>' << content;
595 
596  if (!_children.empty())
597  out << format._endl;
598 
599  for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
600  (*it)->pretty_write_worker(out, format, indent+1);
601 
602  for(int i=indent; i--; )
603  out << XML_INDENT_SPACE;
604 
605  out << "</" << EncodeXMLString(*this) << '>' << format._endl;
606  } else
607  out << "/>" << format._endl;
608 }
609 
610 
612 void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const
613 {
614  // strip the first line feed from _leading
615  const char* leading = _leading.c_str();
616  if (*leading == '\n') ++leading;
617 
618  if (!*leading)
619  for(int i=indent; i--; )
620  out << XML_INDENT_SPACE;
621  else
622  out << leading;
623 
624  out << '<' << EncodeXMLString(*this);
625 
626  for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
627  out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
628 
629  // strip leading white space from content
630  const char* content = _content.c_str();
631  while(isspace((unsigned char)*content)) ++content;
632 
633  if (_children.empty() && !*content)
634  out << "/>";
635  else {
636  out << '>';
637 
638  if (_cdata_content)
639  out << CDATA_START << _content << CDATA_END;
640  else if (!*content)
641  out << format._endl;
642  else
643  out << content;
644 
645  Children::const_iterator it = _children.begin();
646 
647  if (it != _children.end()) {
648  for(; it!=_children.end(); ++it)
649  (*it)->smart_write_worker(out, format, indent+1);
650 
651  // strip the first line feed from _end_leading
652  const char* end_leading = _end_leading.c_str();
653  if (*end_leading == '\n') ++end_leading;
654 
655  if (!*end_leading)
656  for(int i=indent; i--; )
657  out << XML_INDENT_SPACE;
658  else
659  out << end_leading;
660  } else
661  out << _end_leading;
662 
663  out << "</" << EncodeXMLString(*this) << '>';
664  }
665 
666  if (_trailing.empty())
667  out << format._endl;
668  else
669  out << _trailing;
670 }
671 
672 
673 std::ostream& operator<<(std::ostream& out, const XMLError& err)
674 {
675  out << err._systemId << "(" << err._line << ") [column " << err._column << "] : "
676  << err._message;
677 
678  return out;
679 }
680 
681 
682 const char* get_xmlsym_end_utf8(const char* p)
683 {
684  for(; *p; ++p) {
685  char c = *p;
686 
687  // NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
688  if (c == '\xC3') // UTF-8 escape character
689  ++p; //TODO only continue on umlaut characters
690  else if (!isalnum(c) && c!='.' && c!='-' && c!='_' && c!=':')
691  break;
692  }
693 
694  return p;
695 }
696 
697 
698 void DocType::parse(const char* p)
699 {
700  while(isspace((unsigned char)*p)) ++p;
701 
702  const char* start = p;
703  p = get_xmlsym_end_utf8(p);
704  _name.assign(start, p-start);
705 
706  while(isspace((unsigned char)*p)) ++p;
707 
708  start = p;
709  p = get_xmlsym_end_utf8(p);
710  std::string keyword(p, p-start); // "PUBLIC" or "SYSTEM"
711 
712  while(isspace((unsigned char)*p)) ++p;
713 
714  if (*p=='"' || *p=='\'') {
715  char delim = *p;
716 
717  start = ++p;
718  while(*p && *p!=delim) ++p;
719 
720  if (*p == delim)
721  _public.assign(start, p++-start);
722  } else
723  _public.erase();
724 
725  while(isspace((unsigned char)*p)) ++p;
726 
727  if (*p=='"' || *p=='\'') {
728  char delim = *p;
729 
730  start = ++p;
731  while(*p && *p!=delim) ++p;
732 
733  if (*p == delim)
734  _system.assign(start, p++-start);
735  } else
736  _system.erase();
737 }
738 
739 
740 void XMLFormat::print_header(std::ostream& out, bool lf) const
741 {
742  out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"";
743 
744  if (_standalone != -1)
745  out << " standalone=\"yes\"";
746 
747  out << "?>";
748 
749  if (lf)
750  out << _endl;
751 
752  if (!_doctype.empty()) {
753  out << "<!DOCTYPE " << _doctype._name;
754 
755  if (!_doctype._public.empty()) {
756  out << " PUBLIC \"" << _doctype._public << '"';
757 
758  if (lf)
759  out << _endl;
760 
761  out << " \"" << _doctype._system << '"';
762  } else if (!_doctype._system.empty())
763  out << " SYSTEM \"" << _doctype._system << '"';
764 
765  out << "?>";
766 
767  if (lf)
768  out << _endl;
769  }
770 
771  for(StyleSheetList::const_iterator it=_stylesheets.begin(); it!=_stylesheets.end(); ++it) {
772  it->print(out);
773 
774  if (lf)
775  out << _endl;
776  }
777 
778 /* if (!_additional.empty()) {
779  out << _additional;
780 
781  if (lf)
782  out << _endl;
783  } */
784 }
785 
787 {
788  out << "<?xml-stylesheet"
789  " href=\"" << _href << "\""
790  " type=\"" << _type << "\"";
791 
792  if (!_title.empty())
793  out << " title=\"" << _title << "\"";
794 
795  if (!_media.empty())
796  out << " media=\"" << _media << "\"";
797 
798  if (!_charset.empty())
799  out << " charset=\"" << _charset << "\"";
800 
801  if (_alternate)
802  out << " alternate=\"yes\"";
803 
804  out << "?>";
805 }
806 
807 
810 {
812 
813  out << *this;
814 
815  return out.str();
816 }
817 
818 
821 {
823 
824  for(const_iterator it=begin(); it!=end(); ++it)
825  out << *it << std::endl;
826 
827  return out.str();
828 }
829 
830 
832 {
833  if (_pos->_children.empty())
834  _pos->_trailing.append(_content);
835  else
836  _pos->_children.back()->_trailing.append(_content);
837 
838  _content.erase();
839 }
840 
841 
843 void XMLReaderBase::XmlDeclHandler(const char* version, const char* encoding, int standalone)
844 {
845  if (version)
846  _format._version = version;
847 
848  if (encoding)
849  _format._encoding = encoding;
850 
851  _format._standalone = standalone;
852 }
853 
854 
857 {
858  const char* s = _content.c_str();
859  const char* e = s + _content.length();
860  const char* p = s;
861 
862  // search for content end leaving only white space for leading
863  for(p=e; p>s; --p)
864  if (!isspace((unsigned char)p[-1]))
865  break;
866 
867  if (p != s) {
868  if (_pos->_children.empty()) { // no children in last node?
869  if (_last_tag == TAG_START)
870  _pos->_content.append(s, p-s);
871  else if (_last_tag == TAG_END)
872  _pos->_trailing.append(s, p-s);
873  else // TAG_NONE at root node
874  p = s;
875  } else
876  _pos->_children.back()->_trailing.append(s, p-s);
877  }
878 
879  std::string leading;
880 
881  if (p != e)
882  leading.assign(p, e-p);
883 
884  XMLNode* node = new XMLNode(name, leading);
885 
886  _pos.add_down(node);
887 
888 #ifdef XMLNODE_LOCATION
889  node->_location = get_location();
890 #endif
891 
892  node->_attributes = attributes;
893 
894  _last_tag = TAG_START;
895  _content.erase();
896 }
897 
900 {
901  const char* s = _content.c_str();
902  const char* e = s + _content.length();
903  const char* p;
904 
905  if (!strncmp(s,CDATA_START,9) && !strncmp(e-3,CDATA_END,3)) {
906  s += 9;
907  p = (e-=3);
908 
909  _pos->_cdata_content = true;
910  } else {
911  // search for content end leaving only white space for _end_leading
912  for(p=e; p>s; --p)
913  if (!isspace((unsigned char)p[-1]))
914  break;
915 
916  _pos->_cdata_content = false;
917  }
918 
919  if (p != s) {
920  if (_pos->_children.empty()) // no children in current node?
921  _pos->_content.append(s, p-s);
922  else if (_last_tag == TAG_START)
923  _pos->_content.append(s, p-s);
924  else
925  _pos->_children.back()->_trailing.append(s, p-s);
926  }
927 
928  if (p != e)
929  _pos->_end_leading.assign(p, e-p);
930 
931  _pos.back();
932 
933  _last_tag = TAG_END;
934  _content.erase();
935 }
936 
937 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
940 {
941 #if defined(XML_UNICODE) || defined(XS_USE_XERCES)
942  _content.append(String_from_XML_Char(s, len));
943 #else
944  _content.append(s, len);
945 #endif
946 }
947 #endif
948 
949 
951 
953 {
954  if (!_stack.empty()) {
955  StackEntry& last = _stack.top();
956 
957  if (last._state < PRE_CLOSED) {
958  write_attributes(last);
959  close_pre(last);
960  }
961 
962  ++last._children;
963  }
964 
966  entry._node_name = name;
967  _stack.push(entry);
968 
969  write_pre(entry);
970 }
971 
973 {
974  if (!_stack.empty()) {
975  write_post(_stack.top());
976 
977  _stack.pop();
978  return true;
979  } else
980  return false;
981 }
982 
984 {
985  _out << '>';
986 
987  entry._state = PRE_CLOSED;
988 }
989 
990 void XMLWriter::write_pre(StackEntry& entry)
991 {
992  if (_format._pretty >= PRETTY_LINEFEED)
993  _out << _format._endl;
994 
995  if (_format._pretty == PRETTY_INDENT) {
996  for(size_t i=_stack.size(); --i>0; )
997  _out << XML_INDENT_SPACE;
998  }
999 
1000  _out << '<' << EncodeXMLString(entry._node_name);
1001  //entry._state = PRE;
1002 }
1003 
1004 void XMLWriter::write_attributes(StackEntry& entry)
1005 {
1006  for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it)
1007  _out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
1008 
1009  entry._state = ATTRIBUTES;
1010 }
1011 
1012 void XMLWriter::write_post(StackEntry& entry)
1013 {
1014  if (entry._state < ATTRIBUTES)
1015  write_attributes(entry);
1016 
1017  if (entry._children || !entry._content.empty()) {
1018  if (entry._state < PRE_CLOSED)
1019  close_pre(entry);
1020 
1021  _out << entry._content;
1022  //entry._state = CONTENT;
1023 
1024  if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
1025  _out << _format._endl;
1026 
1027  if (_format._pretty==PRETTY_INDENT && entry._content.empty()) {
1028  for(size_t i=_stack.size(); --i>0; )
1029  _out << XML_INDENT_SPACE;
1030  }
1031 
1032  _out << "</" << EncodeXMLString(entry._node_name) << ">";
1033  } else {
1034  _out << "/>";
1035  }
1036 
1037  entry._state = POST;
1038 }
1039 
1040 
1041 } // namespace XMLStorage
XMLNode(const XS_String &name)
Definition: xmlstorage.h:984
Definition: graphics.c:170
const XMLNode * _cur
Definition: xmlstorage.h:1907
#define isspace(c)
Definition: acclib.h:69
const XML_Char * version
Definition: expat.h:187
#define XS_FLOATFMT_STR
Definition: xmlstorage.h:410
#define XS_VALUE_STR
Definition: xmlstorage.h:413
#define XS_nicmp
Definition: xmlstorage.h:243
#define XS_len
Definition: xmlstorage.h:246
basic_ostream< char, char_traits< char > > ostream
Definition: _iosfwd.h:121
basic_ostringstream< char, char_traits< char >, allocator< char > > ostringstream
Definition: _iosfwd.h:127
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
const XS_String XS_PROPERTY
Definition: xmlstorage.cpp:63
POINT last
Definition: font.c:46
bool filter(const XPath &xpath, XMLNode &target) const
copy matching tree nodes using the given XPath filter expression
Definition: xmlstorage.cpp:321
GLsizei const GLchar ** path
Definition: glext.h:7234
static std::string unescape(const char *s, char b, char e)
remove escape characters from zero terminated string
Definition: xmlstorage.cpp:67
const XML_Char const XML_Char * encoding
Definition: expat.h:187
uint8_t entry
Definition: isohybrid.c:63
#define XS_EMPTY_STR
Definition: xmlstorage.h:406
#define equal(x, y)
Definition: reader.cc:56
void add_child(XMLNode *child)
add a new child node
Definition: xmlstorage.h:1067
void create(const XS_String &name)
create node and move to it
Definition: xmlstorage.cpp:952
#define o(x)
Definition: extensions.c:56
GLuint buffer
Definition: glext.h:5915
std::ostringstream fast_ostringstream
Definition: xmlstorage.h:2696
#define XS_EMPTY
Definition: xmlstorage.h:424
virtual void StartElementHandler(const XS_String &name, const XMLNode::AttributeMap &attributes)
notifications about XML start tag
Definition: xmlstorage.cpp:856
GLuint GLuint end
Definition: gl.h:1545
#define XS_KEY_STR
Definition: xmlstorage.h:412
XMLNode * find(XMLNode *node) const
Definition: xmlstorage.cpp:184
const XS_String XS_KEY
Definition: xmlstorage.cpp:61
Definition: query.h:86
static HWND child
Definition: cursoricon.c:298
#define XS_TRUE_STR
Definition: xmlstorage.h:407
#define alloca
Definition: malloc.h:361
bool back()
go back to previous position
Definition: xmlstorage.cpp:972
GLuint const GLchar * name
Definition: glext.h:6031
#define sprintf(buf, format,...)
Definition: sprintf.c:55
GLuint n
Definition: s_context.h:57
struct node node
container for XMLWriter state information
Definition: xmlstorage.h:2974
basic_ostream< _CharT, _Traits > &_STLP_CALL endl(basic_ostream< _CharT, _Traits > &__os)
Definition: _ostream.h:357
#define _(X)
Definition: i386-dis.c:36
map of XML node attributes
Definition: xmlstorage.h:894
const XML_Char const XML_Char int standalone
Definition: expat.h:187
#define e
Definition: ke_i.h:82
void go_to(const XMLNode *child)
go to specified node
Definition: xmlstorage.h:1911
static size_t elem
Definition: string.c:68
#define XS_FALSE
Definition: xmlstorage.h:426
virtual void XmlDeclHandler(const char *version, const char *encoding, int standalone)
store XML version and encoding into XML reader
Definition: xmlstorage.cpp:843
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
#define BUFFER_LEN
Definition: utility.h:97
static clock_t begin
Definition: xmllint.c:466
#define XS_INTFMT_STR
Definition: xmlstorage.h:409
#define CDATA_START
Definition: xmlstorage.h:435
XS_String DecodeXMLString(const std::string &str)
decode XML string literals
Definition: xmlstorage.cpp:478
r l[0]
Definition: byte_order.h:167
const XS_String XS_VALUE
Definition: xmlstorage.cpp:62
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
const XMLNode * const_find(const XMLNode *node) const
Definition: xmlstorage.cpp:195
int count(const XPath &xpath) const
count the nodes matching the given relative XPath expression
Definition: xmlstorage.h:1244
if(!(yy_init))
Definition: macro.lex.yy.c:717
static int bracket
Definition: adnsresfilter.c:59
in memory representation of an XML node
Definition: xmlstorage.h:854
AttributeMap _attributes
Definition: xmlstorage.h:1271
#define XS_strstr
Definition: xmlstorage.h:249
void go_to(XMLNode *child)
go to specified node
Definition: xmlstorage.h:1786
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static FILE * out
Definition: regtests2xml.c:44
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
std::string _content
Definition: xmlstorage.h:1274
static HRESULT get_location(HTMLInnerWindow *This, HTMLLocation **ret)
Definition: htmlwindow.c:43
std::string _leading
Definition: xmlstorage.h:1273
void assign(const XS_String &s)
Definition: xmlstorage.h:338
int ret
const XMLNode * find_relative(const XPath &xpath) const
XPath find function (const)
Definition: xmlstorage.cpp:251
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
#define XS_PROPERTY_STR
Definition: xmlstorage.h:414
GLenum GLsizei len
Definition: glext.h:6722
void print(std::ostream &out) const
Definition: xmlstorage.cpp:786
#define XS_CHAR
Definition: xmlstorage.h:236
char string[160]
Definition: util.h:11
std::string str() const
return formated error message
Definition: xmlstorage.cpp:809
void original_write_worker(std::ostream &out) const
write node with children tree to output stream using original white space
Definition: xmlstorage.cpp:528
XS_String str() const
return merged error strings
Definition: xmlstorage.cpp:820
bool matches(const XMLNode &node, int &n) const
Definition: xmlstorage.cpp:206
void print_header(std::ostream &out, bool lf=true) const
Definition: xmlstorage.cpp:740
const char * parse(const char *path)
Definition: xmlstorage.cpp:142
#define XS_FALSE_STR
Definition: xmlstorage.h:408
GLuint start
Definition: gl.h:1545
Definition: services.c:325
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
virtual void EndElementHandler()
notifications about XML end tag
Definition: xmlstorage.cpp:899
std::string EncodeXMLString(const XS_String &str, bool cdata)
encode XML string literals
Definition: xmlstorage.cpp:374
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define LPXSSTR
Definition: xmlstorage.h:238
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
Definition: name.c:36
#define XS_TEXT(x)
Definition: xmlstorage.h:237
void init(const char *path)
Definition: xmlstorage.cpp:225
#define XS_INTFMT
Definition: xmlstorage.h:427
bool go(const XPath &xpath)
move to the position defined by xpath in XML tree
Definition: xmlstorage.cpp:128
GLfloat GLfloat p
Definition: glext.h:8902
bool go(const XPath &xpath)
move to the position defined by xpath in XML tree
Definition: xmlstorage.cpp:114
CardRegion * from
Definition: spigame.cpp:19
void move(Children &other)
Definition: xmlstorage.h:929
#define CDATA_END
Definition: xmlstorage.h:436
XMLNode * create_relative(const XPath &xpath)
relative XPath create function
Definition: xmlstorage.cpp:279
void close_pre(StackEntry &entry)
Definition: xmlstorage.cpp:983
virtual void DefaultHandler(const std::string &s)
store content, white space and comments
Definition: xs-native.cpp:434
#define XS_FLOATFMT
Definition: xmlstorage.h:428
#define XS_TRUE
Definition: xmlstorage.h:425
char XML_Char
XS_String get(const T &attr_name, LPCXSSTR def=XS_EMPTY_STR) const
read only access to an attribute
Definition: xmlstorage.h:1095
string class for TCHAR strings
Definition: xmlstorage.h:287
#define LPCXSSTR
Definition: xmlstorage.h:239
static XS_String s_empty_attr
Definition: xmlstorage.h:2986