NCBI C++ ToolKit
document.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /*
2  * Copyright (C) 2001-2003 Peter J Jones (pjones@pmade.org)
3  * All Rights Reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name of the Author nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
23  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * $Id: document.cpp 103111 2024-09-10 12:49:20Z satskyse $
35  * NOTE: This file was modified from its original version 0.6.0
36  * to fit the NCBI C++ Toolkit build framework and
37  * API and functionality requirements.
38  */
39 
40 /** @file
41  * This file contains the implementation of the xml::document class.
42 **/
43 
44 // xmlwrapp includes
46 #include <misc/xmlwrapp/node.hpp>
47 #include <misc/xmlwrapp/dtd.hpp>
48 #include <misc/xmlwrapp/schema.hpp>
50 #include "stylesheet_impl.hpp"
51 #include "utility.hpp"
52 #include "document_impl.hpp"
53 #include "node_manip.hpp"
54 #include "https_input_impl.hpp"
55 
56 // standard includes
57 #include <new>
58 #include <memory>
59 #include <iterator>
60 #include <iostream>
61 #include <algorithm>
62 #include <stdexcept>
63 #include <string.h>
64 
65 // libxml includes
66 #include <libxml/parser.h>
67 #include <libxml/parserInternals.h>
68 #include <libxml/SAX.h>
69 #include <libxml/xmlversion.h>
70 #include <libxml/tree.h>
71 #include <libxml/xinclude.h>
72 #include <libxml/xmlsave.h>
73 #include <libxml/c14n.h>
74 
75 
76 // Workshop compiler define
77 #include <ncbiconf.h>
78 
79 
80 using namespace xml;
81 using namespace xml::impl;
82 
83 
84 //####################################################################
85 /*
86  * This is a hack to fix a problem with a change in the libxml2 API for
87  * versions starting at 2.6.0
88  */
89 #if LIBXML_VERSION >= 20600
90 # define initxmlDefaultSAXHandler xmlSAX2InitDefaultSAXHandler
91 # include <libxml/SAX2.h>
92 #endif
93 
95 {
96  switch (op) {
98  return -1;
100  return -1;
101  case xml::c14n_1_0:
102  return XML_C14N_1_0;
104  return XML_C14N_EXCLUSIVE_1_0;
105  case xml::c14n_1_1:
106  return XML_C14N_1_1;
107  }
108 
109  throw xml::exception("Unknown canonicalization option");
110 }
111 
112 
113 struct cmp
114 {
115  bool operator() (const xml::node &lhs, const xml::node &rhs)
116  {
117  if ( lhs.get_type() != xml::node::type_element ) return true;
118  if ( rhs.get_type() != xml::node::type_element ) return false;
119  return strcmp( lhs.get_name(), rhs.get_name() ) < 0;
120  }
121 };
123 {
124  n.sort(cmp());
125  for (xml::node::iterator k = n.begin(); k != n.end(); ++k)
126  if (k->get_type() == xml::node::type_element)
128 }
129 
131 {
132  xml::node::iterator k = n.begin();
133  while (k != n.end()) {
134  if (k->get_type() == xml::node::type_comment)
135  k = n.erase(k);
136  else {
138  ++k;
139  }
140  }
141 }
142 
144 {
145  if (n.get_type() == xml::node::type_element)
146  n.get_attributes().sort();
147  for (xml::node::iterator k = n.begin(); k != n.end(); ++k)
149 }
150 
152 {
153  n.sort_namespace_definitions();
154  for (xml::node::iterator k = n.begin(); k != n.end(); ++k)
156 }
157 
158 
159 static void set_parser_context_options(xmlParserCtxtPtr ctxt)
160 {
161  if (ctxt == NULL)
162  return;
163 
164  // Parser context options
165  // XML_PARSE_HUGE - overrides the default libxml2 parser limits. If it is
166  // not here then certain large documents will not be parsed
167  // XML_PARSE_NODICT - when xmlCtxtUseOptions() is called, it sets the
168  // context field 'dictNames' to 1. We would prefer not
169  // to change the initialized context so this flag is
170  // supplied.
171  int options = XML_PARSE_HUGE | XML_PARSE_NODICT;
172 
173  // When the xmlCtxtUseOptions() is called it updates the context
174  // 'loadsubset' field. To avoid updating it the XML_PARSE_DTDLOAD flag
175  // may need to be supplied if the user requested the loading external DTD
176  // (default). This behavior is controlled by the user via the
177  // xml::init::load_external_subsets() call.
179  options |= XML_PARSE_DTDLOAD;
180 
181  // When the xmlCtxtUseOptions() is called it updates the context
182  // 'keepBlanks' field. To avoid updating it the XML_PARSE_NOBLANKS flag
183  // may need to be supplied.
184  // The user controls this behavior via the xml::init::remove_whitespace()
185  // call.
187  options |= XML_PARSE_NOBLANKS;
188 
189  // When the xmlCtxtUseOptions() is called it updates the context
190  // 'validate' field. To avoid updating it the XML_PARSE_DTDVALID flag may
191  // need to be supplied.
192  // The user controls this behavior via the xml::init::validate_xml() call.
194  options |= XML_PARSE_DTDVALID;
195 
196  // When the xmlCtxtUseOptions() is called it updates the context
197  // 'replaceEntities' field. To avoid updating it the XML_PARSE_NOENT flag
198  // may need to be supplied.
199  // The user controls this behavior via the xml::init::substitute_entities()
200  // call.
202  options |= XML_PARSE_NOENT;
203 
204  // Set the context options
205  xmlCtxtUseOptions(ctxt, options);
206 }
207 
208 
209 //####################################################################
210 namespace {
211  const char const_default_encoding[] = "ISO-8859-1";
212 
213  // Callbacks for validating internal DTD
214  extern "C" void cb_dtd_valid_error (void *v, const char *message, ...);
215  extern "C" void cb_dtd_valid_warning (void *v, const char *message, ...);
216 
217  // Callbacks for the tree parser
218  extern "C" void cb_tree_parser_fatal_error (void *v,
219  const char *message, ...);
220  extern "C" void cb_tree_parser_error (void *v, const char *message, ...);
221  extern "C" void cb_tree_parser_warning (void *v, const char *message, ...);
222  extern "C" void cb_tree_parser_ignore (void*, const xmlChar*, int);
223 }
224 //####################################################################
226  pimpl_(new doc_impl)
227 {}
228 //####################################################################
229 
230 
231 // This custom xmlSAXParseFileWithData_Custom() function is basically a copy of
232 // the standard libxml2 xmlSAXParseFileWithData() function with a small change.
233 // It allows to set the appropriate context options, notably the ability to
234 // parse huge XML documents.
235 // The standard libxml2 function hides the parser context and therefore the
236 // options are not available.
237 static xmlDocPtr xmlSAXParseFileWithData_Custom(xmlSAXHandlerPtr sax,
238  const char *filename,
239  void *data)
240 {
241  xmlDocPtr ret;
242  xmlParserCtxtPtr ctxt;
243 
244  ctxt = xmlCreateFileParserCtxt(filename);
245  if (ctxt == NULL)
246  return NULL;
247 
248  // This is the major difference to the standard libxml2 version: setting
249  // the context options.
251 
252  if (sax != NULL) {
253  if (ctxt->sax != NULL)
254  xmlFree(ctxt->sax);
255  ctxt->sax = sax;
256  }
257 
258  if (data!=NULL)
259  ctxt->_private = data;
260 
261  if (ctxt->directory == NULL)
262  ctxt->directory = xmlParserGetDirectory(filename);
263 
264  xmlParseDocument(ctxt);
265  if (ctxt->wellFormed) {
266  ret = ctxt->myDoc;
267  if (ret != NULL) {
268  if (ctxt->input->buf->compressed > 0)
269  ret->compression = 9;
270  else
271  ret->compression = ctxt->input->buf->compressed;
272  }
273  }
274  else {
275  ret = NULL;
276  xmlFreeDoc(ctxt->myDoc);
277  ctxt->myDoc = NULL;
278  }
279  if (sax != NULL)
280  ctxt->sax = NULL;
281  xmlFreeParserCtxt(ctxt);
282  return ret;
283 }
284 
285 
286 xml::document::document (const char * filename,
287  error_messages * messages,
289  pimpl_(NULL)
290 {
291  if (!filename)
292  throw xml::exception("invalid file name");
293 
294  xmlSAXHandler sax;
295  memset(&sax, 0, sizeof(sax));
296  initxmlDefaultSAXHandler(&sax, 0);
297 
298  sax.warning = cb_tree_parser_warning;
299  sax.error = cb_tree_parser_error;
300  sax.fatalError = cb_tree_parser_fatal_error;
301 
303  sax.ignorableWhitespace = cb_tree_parser_ignore;
304 
305  error_messages * temp(messages);
306  std::unique_ptr<error_messages> msgs;
307  if (!messages)
308  msgs.reset(temp = new error_messages);
309  else
310  messages->get_messages().clear();
311 
312  // Wrap the libxml2 call with https error collecting
314  xmlDocPtr tmpdoc = xmlSAXParseFileWithData_Custom(&sax, filename, temp);
316 
317  if (!tmpdoc) {
318  // It is a common case that the file does not exist or cannot be
319  // opened. libxml2 does not recognise it so make a test here to
320  // have a better error message.
321  FILE *test(fopen(filename, "r"));
322  if (test == NULL) {
323  error_message msg("Cannot open file",
325  0, filename);
326  temp->get_messages().push_back(msg);
327  throw parser_exception(*temp);
328  }
329  fclose(test);
330  }
331 
332  if (is_failure(temp, how) || !tmpdoc) {
333  if (tmpdoc) xmlFreeDoc(tmpdoc);
334  throw parser_exception(*temp);
335  }
336 
337  pimpl_ = new doc_impl;
338  set_doc_data(tmpdoc);
339 }
340 //####################################################################
342  size_type size,
343  error_messages * messages,
345  pimpl_(NULL)
346 {
347  if (!data)
348  throw xml::exception("invalid data pointer");
349 
350  xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(data,
352  "memory buffer is too large"));
353  if (ctxt == 0)
354  throw std::bad_alloc();
355 
357 
358  xmlSAXHandler sax;
359  memset(&sax, 0, sizeof(sax));
360  initxmlDefaultSAXHandler(&sax, 0);
361 
362  sax.warning = cb_tree_parser_warning;
363  sax.error = cb_tree_parser_error;
364  sax.fatalError = cb_tree_parser_fatal_error;
365 
367  sax.ignorableWhitespace = cb_tree_parser_ignore;
368 
369  if (ctxt->sax)
370  xmlFree(ctxt->sax);
371  ctxt->sax = &sax;
372 
373  error_messages * temp(messages);
374  std::unique_ptr<error_messages> msgs;
375  if (!messages)
376  msgs.reset(temp = new error_messages);
377  else
378  messages->get_messages().clear();
379  ctxt->_private = temp;
380 
381  // Wrap the libxml2 call with https errors collecting
383  int ret(xmlParseDocument(ctxt));
385 
386  if (!ctxt->wellFormed || ret != 0 || is_failure(temp, how)) {
387  if (ctxt->myDoc)
388  xmlFreeDoc(ctxt->myDoc);
389  ctxt->sax = 0;
390  xmlFreeParserCtxt(ctxt);
391 
392  throw parser_exception(*temp);
393  }
394 
395  pimpl_ = new doc_impl;
396  set_doc_data(ctxt->myDoc);
397  ctxt->sax = 0;
398 
399  xmlFreeParserCtxt(ctxt);
400 }
401 //####################################################################
402 xml::document::document (const char *root_name) :
403  pimpl_(new doc_impl(root_name))
404 {}
405 //####################################################################
407  std::unique_ptr<doc_impl> ap(pimpl_ = new doc_impl);
408  pimpl_->set_root_node(n);
409  ap.release();
410 }
411 //####################################################################
413  pimpl_(new doc_impl)
414 {
415  set_doc_data_from_xslt(doc_proxy.result_, doc_proxy.style_sheet_);
416  // Now the result doc is owned
417  doc_proxy.release();
418 }
419 //####################################################################
420 static const std::size_t const_buffer_size = 4096;
421 
422 xml::document::document (std::istream & stream,
423  error_messages * messages,
425  pimpl_(NULL)
426 {
427  /* Deal with the SAX handler first */
428  xmlSAXHandler sax;
429 
430  memset(&sax, 0, sizeof(sax));
431  initxmlDefaultSAXHandler(&sax, 0);
432 
433  sax.warning = cb_tree_parser_warning;
434  sax.error = cb_tree_parser_error;
435  sax.fatalError = cb_tree_parser_fatal_error;
436 
437 
439  sax.ignorableWhitespace = cb_tree_parser_ignore;
440 
441  /* Make sure we have where to collect messages */
442  error_messages * temp(messages);
443  std::unique_ptr<error_messages> msgs;
444  if (!messages)
445  msgs.reset(temp = new error_messages);
446  else
447  messages->get_messages().clear();
448 
449  /* Make sure that the stream is not empty */
450  if (stream && (stream.eof() ||
451  stream.peek() == std::istream::traits_type::eof()))
452  {
453  temp->get_messages().push_back(error_message("empty xml document",
455  0, ""));
456  throw parser_exception(*temp);
457  }
458 
459  /* Create the context to parse the stream */
460  xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(&sax, 0, 0, 0, 0);
461  if (ctxt == 0)
462  throw std::bad_alloc();
463  ctxt->_private = temp;
464 
466 
467  // Wrap the libxml2 calls with the https error collecting
469 
470  /* Parse the document chunk by chunk */
472  while (stream.read(buffer, const_buffer_size) || stream.gcount())
473  {
474  if (xmlParseChunk(ctxt, buffer, static_cast<int>(stream.gcount()), 0) != 0)
475  break;
476  }
477  xmlParseChunk(ctxt, 0, 0, 1);
479 
480  /* The parsing has been finished, check the results */
481  if (!ctxt->wellFormed || ctxt->myDoc == NULL || is_failure(temp, how))
482  {
483  if (ctxt->myDoc)
484  xmlFreeDoc(ctxt->myDoc);
485  xmlFreeParserCtxt(ctxt);
486 
487  throw parser_exception(*temp);
488  }
489 
490  /* Fine, the doc is OK */
491 
492  pimpl_ = new doc_impl;
493  set_doc_data(ctxt->myDoc);
494  xmlFreeParserCtxt(ctxt);
495 }
496 //####################################################################
498  pimpl_(new doc_impl(*(other.pimpl_)))
499 {} /* NCBI_FAKE_WARNING */
500 //####################################################################
502  document tmp(other); /* NCBI_FAKE_WARNING */
503  swap(tmp);
504  return *this;
505 }
506 //####################################################################
508  document tmp(other);
509  swap(tmp);
510  return *this;
511 }
512 //####################################################################
514  pimpl_(other.pimpl_)
515 {
516  other.pimpl_ = NULL;
517 }
518 //####################################################################
520 {
521  if (this != &other) {
522  if (pimpl_ != NULL)
523  delete pimpl_;
524  pimpl_ = other.pimpl_;
525  other.pimpl_ = NULL;
526  }
527  return *this;
528 }
529 //####################################################################
531  std::swap(pimpl_, other.pimpl_);
532 }
533 //####################################################################
535  if (pimpl_ != NULL)
536  delete pimpl_;
537 }
538 //####################################################################
540  pimpl_->root_.set_node_data(xmlDocGetRootElement(pimpl_->doc_));
541  return pimpl_->root_;
542 }
543 //####################################################################
545  pimpl_->root_.set_node_data(xmlDocGetRootElement(pimpl_->doc_));
546  return pimpl_->root_;
547 }
548 //####################################################################
550  pimpl_->set_root_node(n);
551 }
552 //####################################################################
554  return pimpl_->version_;
555 }
556 //####################################################################
558  const xmlChar * old_version = pimpl_->doc_->version;
559 
560  pimpl_->doc_->version = xmlStrdup(
561  reinterpret_cast<const xmlChar*>(version));
562 
563  if ( pimpl_->doc_->version == 0)
564  throw std::bad_alloc();
565 
566  pimpl_->version_ = version;
567  if (old_version)
568  xmlFree(const_cast<char*>(reinterpret_cast<const char*>(old_version)));
569 }
570 //####################################################################
572  if (pimpl_->encoding_.empty())
573  pimpl_->encoding_ = const_default_encoding;
574  return pimpl_->encoding_;
575 }
576 //####################################################################
577 void xml::document::set_encoding (const char *encoding) {
578  pimpl_->encoding_ = encoding;
579 
580  if (pimpl_->doc_->encoding)
581  xmlFree(const_cast<xmlChar*>(pimpl_->doc_->encoding));
582 
583  pimpl_->doc_->encoding = xmlStrdup(
584  reinterpret_cast<const xmlChar*>(encoding));
585 
586  if (!pimpl_->doc_->encoding)
587  throw std::bad_alloc();
588 }
589 //####################################################################
591  return pimpl_->doc_->standalone == 1;
592 }
593 //####################################################################
595  pimpl_->doc_->standalone = sa ? 1 : 0;
596 }
597 //####################################################################
599  // xmlXIncludeProcess does not return what is says it does
600  return xmlXIncludeProcess(pimpl_->doc_) >= 0;
601 }
602 //####################################################################
604  return pimpl_->doc_->intSubset != 0;
605 }
606 //####################################################################
608  if (!has_internal_subset())
609  throw xml::exception("The document does not have internal subset.");
610  pimpl_->internal_subset_.set_dtd_data(pimpl_->doc_->intSubset);
611  return pimpl_->internal_subset_;
612 }
613 //####################################################################
615  return pimpl_->doc_->extSubset != 0;
616 }
617 //####################################################################
619  if (!has_external_subset())
620  throw xml::exception("The document does not have external subset.");
621  pimpl_->external_subset_.set_dtd_data(pimpl_->doc_->extSubset);
622  return pimpl_->external_subset_;
623 }
624 //####################################################################
626  warnings_as_errors_type how) const {
627  error_messages * temp(messages_);
628  std::unique_ptr<error_messages> msgs;
629  if (!messages_)
630  msgs.reset(temp = new error_messages);
631 
632  xmlValidCtxt vctxt;
633 
634  memset(&vctxt, 0, sizeof(vctxt));
635  vctxt.error = cb_dtd_valid_error;
636  vctxt.warning = cb_dtd_valid_warning;
637  vctxt.userData = temp;
638 
639  temp->get_messages().clear();
640 
641  // Wrap the libxml2 call with the https error collecting
643  int retCode = xmlValidateDocument(&vctxt, pimpl_->doc_);
645 
646  if (retCode == 0)
647  return false;
648  if (temp->has_errors())
649  return false;
650  if (temp->has_warnings()) {
651  if (how == type_warnings_are_errors)
652  return false;
653  }
654  return true;
655 }
656 //####################################################################
657 bool document::validate (const dtd& dtd_, error_messages* messages_,
658  warnings_as_errors_type how) const {
659  return dtd_.validate(*this, messages_, how);
660 }
661 //####################################################################
662 bool document::validate (const schema& schema_, error_messages* messages_,
663  warnings_as_errors_type how) const {
664  return schema_.validate(*this, messages_, how);
665 }
666 //####################################################################
667 void document::set_external_subset (const dtd& dtd_) {
668  if (!dtd_.get_raw_pointer())
669  throw xml::exception("xml::document::set_external_subset "
670  "dtd is not loaded");
671 
672  xmlDtdPtr copy = xmlCopyDtd(
673  static_cast<xmlDtdPtr>(dtd_.get_raw_pointer()));
674  if (copy == NULL)
675  throw xml::exception("Error copying DTD");
676 
677  if (pimpl_->doc_->extSubset != 0)
678  xmlFreeDtd(pimpl_->doc_->extSubset);
679  pimpl_->doc_->extSubset = copy;
680 }
681 
682 //####################################################################
684  #ifdef NCBI_COMPILER_WORKSHOP
685  xml::document::size_type dist(0);
686  xml::node::const_iterator first(begin()), last(end());
687  for (; first != last; ++first) { ++dist; }
688  return dist;
689  #else
690  return static_cast<xml::document::size_type>(std::distance(begin(),
691  end()));
692  #endif
693 }
694 //####################################################################
696  return node::iterator(pimpl_->doc_->children);
697 }
698 //####################################################################
700  return node::const_iterator(pimpl_->doc_->children);
701 }
702 //####################################################################
704  return node::iterator(0);
705 }
706 //####################################################################
708  return node::const_iterator(0);
709 }
710 //####################################################################
711 void xml::document::push_back (const node &child) {
712  if (child.get_type() == node::type_element)
713  throw xml::exception("xml::document::push_back "
714  "can't take element type nodes");
715  xml::impl::node_insert(reinterpret_cast<xmlNodePtr>(pimpl_->doc_), 0,
716  static_cast<xmlNodePtr>(
717  const_cast<node&>(child).get_node_data()));
718 }
719 //####################################################################
721  if (n.get_type() == node::type_element)
722  throw xml::exception("xml::document::insert "
723  "can't take element type nodes");
724  return node::iterator(
725  xml::impl::node_insert(reinterpret_cast<xmlNodePtr>(pimpl_->doc_),
726  0,
727  static_cast<xmlNodePtr>(
728  const_cast<node&>(n).get_node_data())));
729 }
730 //####################################################################
732  const node &n) {
733  if (n.get_type() == node::type_element)
734  throw xml::exception("xml::document::insert "
735  "can't take element type nodes");
736  return node::iterator(
737  xml::impl::node_insert(reinterpret_cast<xmlNodePtr>(pimpl_->doc_),
738  static_cast<xmlNodePtr>(
739  position.get_raw_node()),
740  static_cast<xmlNodePtr>(
741  const_cast<node&>(n).get_node_data())));
742 }
743 //####################################################################
745  const node &new_node) {
746  if (old_node->get_type() == node::type_element ||
747  new_node.get_type() == node::type_element) {
748  throw xml::exception("xml::document::replace "
749  "can't replace element type nodes");
750  }
751 
752  return node::iterator(
754  static_cast<xmlNodePtr>(old_node.get_raw_node()),
755  static_cast<xmlNodePtr>(
756  const_cast<node&>(new_node).get_node_data())));
757 }
758 //####################################################################
760  if (to_erase->get_type() == node::type_element)
761  throw xml::exception("xml::document::erase "
762  "can't erase element type nodes");
763  return node::iterator(
765  static_cast<xmlNodePtr>(to_erase.get_raw_node())));
766 }
767 //####################################################################
770  while (first != last)
771  first = erase(first);
772  return first;
773 }
774 //####################################################################
776  save_option_flags flags) const {
777  int compression_level = flags & 0xFFFF;
778 
779  s.clear();
780 
781  // Compression level is currently not analyzed by libxml2
782  // So this might work in the future implementations but is ignored now.
783 
784  if (pimpl_->xslt_stylesheet_ != 0) {
785  if (!xslt::impl::is_xml_output_method(pimpl_->xslt_stylesheet_)) {
786  std::swap(pimpl_->doc_->compression, compression_level);
787  xslt::impl::save_to_string(pimpl_->doc_,
788  pimpl_->xslt_stylesheet_, s);
789  std::swap(pimpl_->doc_->compression, compression_level);
790  return;
791  }
792  }
793 
794  int libxml2_options = convert_to_libxml2_save_options(flags);
795 
796  // In theory it was possible to use the pimpl_->doc_->encoding
797  // value however a cached value is used instead.
798  const char *enc = pimpl_->encoding_.empty() ? 0 : pimpl_->encoding_.c_str();
799  xmlSaveCtxtPtr ctxt = xmlSaveToIO(save_to_string_cb, NULL, &s,
800  enc, libxml2_options);
801 
802  if (ctxt) {
803  std::swap(pimpl_->doc_->compression, compression_level);
804  xmlSaveDoc(ctxt, pimpl_->doc_);
805  std::swap(pimpl_->doc_->compression, compression_level);
806  xmlSaveClose(ctxt); // xmlSaveFlush() is called in xmlSaveClose()
807  }
808 }
809 //####################################################################
811  std::string & str,
812  canonicalization_option c14n_option,
813  canonicalization_comments_option comments_option,
814  canonicalization_format_option format_option,
815  canonicalization_node_sort_option node_sort_option) const
816 {
817  if (pimpl_->xslt_stylesheet_ != 0)
818  if (!xslt::impl::is_xml_output_method(pimpl_->xslt_stylesheet_))
819  throw xml::exception("cannot canonicalize the document: "
820  "it holds xslt transformation results "
821  "which are not an xml");
822 
823  int libxml2_mode = -1; // libxml2 options start from 0 and go up
824  if (c14n_option != xml::sort_attr_and_ns &&
825  c14n_option != xml::sort_attr_and_ns_no_decl)
826  libxml2_mode = c14n_op_to_libxml2_op(c14n_option);
827  int libxml2_with_comments = 0;
828  if (comments_option == keep_comments)
829  libxml2_with_comments = 1;
830 
831  // Here: the document format could be a mess. A part of it could come from
832  // a nicely formatted file and then some nodes could be added
833  // programmatically without formatting.
834  // The libxml2 library allows to skip the formatting text nodes only
835  // at the time of initial parsing. So if the formatting is required
836  // the document we have at hand has to be saved and loaded again with
837  // stripping formatting nodes.
838 
839  // Serialize and deserialize: this covers the XSLT results processing
840  // and checks if the document is well formed
841  bool old_remove_whitespaces = init::get_remove_whitespace();
842  std::string serialized_doc;
843 
844  save_to_string(serialized_doc, save_op_no_format);
845  if (format_option == with_formatting)
847  else
849 
850  document tmp_doc;
851  try {
852  tmp_doc = document(serialized_doc.c_str(), serialized_doc.size(), NULL,
854  } catch (...) {
855  init::remove_whitespace(old_remove_whitespaces);
856  throw;
857  }
858 
859  // Now, recursively sort the nodes in the document
860  // The sorting must be done on a copy of the document to avoid any changes
861  // in the original document
862  if (node_sort_option == with_node_sorting)
864 
865  if (format_option == with_formatting) {
866  // It was loaded with stripped formatting whitespaces.
867  // Now we save and load keeping whitespaces
869  // save_op_default makes libxml2 to insert the formatting
870  tmp_doc.save_to_string(serialized_doc, save_op_default);
871  // Load the document with saved formatting nodes
872  tmp_doc = document(serialized_doc.c_str(), serialized_doc.size(), NULL,
874  }
875 
876  // Restore the previous value remove whitespaces flag
877  init::remove_whitespace(old_remove_whitespaces);
878 
879  if (libxml2_mode != -1) {
880  // Finally, canonicalize the temporary document
881  xmlChar * result = NULL;
882  int size = xmlC14NDocDumpMemory(tmp_doc.pimpl_->doc_,
883  NULL, libxml2_mode,
884  NULL, libxml2_with_comments,
885  &result);
886  if (size < 0)
887  throw xml::exception("xml::document::save_to_string_canonical "
888  "failed to canonicalize");
889 
890  str.assign(reinterpret_cast<const char *>(result), size);
891  if (result != NULL)
892  xmlFree(result);
893  } else {
894  node & root_node = tmp_doc.get_root_node();
895 
896  // No real canonicalization required. The following will be done:
897  // - remove comments if required
898  // - sort attributes
899  // - sort namespace definitions
900  if (comments_option == strip_comments) {
901  if (root_node.get_type() == xml::node::type_comment) {
902  str.assign("");
903  return;
904  }
905  remove_comments_recursively(root_node);
906  }
907 
908  sort_attributes_recursively(root_node);
910 
911 
913  if (c14n_option == xml::sort_attr_and_ns_no_decl)
915  if (format_option == without_formatting)
917 
918  tmp_doc.save_to_string(str, flags);
919  }
920 }
921 //####################################################################
922 void xml::document::save_to_stream (std::ostream &stream,
923  save_option_flags flags) const {
924  int compression_level = flags & 0xFFFF;
925 
926  // Compression level is currently not analyzed by libxml2
927  // So this might work in the future implementations but is ignored now.
928 
929  if (pimpl_->xslt_stylesheet_ != 0) {
930  if (!xslt::impl::is_xml_output_method(pimpl_->xslt_stylesheet_)) {
931  std::swap(pimpl_->doc_->compression, compression_level);
932  std::string s;
933  xslt::impl::save_to_string(pimpl_->doc_,
934  pimpl_->xslt_stylesheet_, s);
935  stream << s;
936  std::swap(pimpl_->doc_->compression, compression_level);
937  return;
938  }
939  }
940 
941  int libxml2_options = convert_to_libxml2_save_options(flags);
942 
943  // In theory it was possible to use the pimpl_->doc_->encoding
944  // value however a cached value is used instead.
945  const char *enc = pimpl_->encoding_.empty() ? 0 : pimpl_->encoding_.c_str();
946  xmlSaveCtxtPtr ctxt = xmlSaveToIO(save_to_stream_cb, NULL, &stream,
947  enc, libxml2_options);
948 
949  if (ctxt) {
950  std::swap(pimpl_->doc_->compression, compression_level);
951  xmlSaveDoc(ctxt, pimpl_->doc_);
952  std::swap(pimpl_->doc_->compression, compression_level);
953  xmlSaveClose(ctxt); // xmlSaveFlush() is called in xmlSaveClose()
954  }
955  std::swap(pimpl_->doc_->compression, compression_level);
956  return;
957 }
958 //####################################################################
959 bool xml::document::save_to_file (const char *filename,
960  save_option_flags flags) const {
961  int compression_level = flags & 0xFFFF;
962 
963  // Compression level is currently not analyzed by libxml2
964  // So this might work in the future implementations but is ignored now.
965 
966  if (pimpl_->xslt_stylesheet_ != 0) {
967  if (!xslt::impl::is_xml_output_method(pimpl_->xslt_stylesheet_)) {
968  std::swap(pimpl_->doc_->compression, compression_level);
969  bool rc = xslt::impl::save_to_file(pimpl_->doc_,
970  pimpl_->xslt_stylesheet_,
971  filename, compression_level);
972  std::swap(pimpl_->doc_->compression, compression_level);
973  return rc;
974  }
975  }
976 
977  int libxml2_options = convert_to_libxml2_save_options(flags);
978 
979  // In theory it was possible to use the pimpl_->doc_->encoding
980  // value however a cached value is used instead.
981  const char *enc = pimpl_->encoding_.empty() ? 0 : pimpl_->encoding_.c_str();
982  xmlSaveCtxtPtr ctxt = xmlSaveToFilename(filename,
983  enc, libxml2_options);
984 
985  if (!ctxt)
986  return false;
987 
988  long rc = 0;
989 
990  std::swap(pimpl_->doc_->compression, compression_level);
991  rc = xmlSaveDoc(ctxt, pimpl_->doc_);
992  std::swap(pimpl_->doc_->compression, compression_level);
993  xmlSaveClose(ctxt); // xmlSaveFlush() is called in xmlSaveClose()
994 
995  return (rc != -1);
996 }
997 //####################################################################
999  // we own the doc now, don't free it!
1000  pimpl_->set_doc_data(static_cast<xmlDocPtr>(data), false);
1001 
1002  if (pimpl_->xslt_stylesheet_)
1003  if (pimpl_->xslt_stylesheet_->_private)
1004  static_cast<xslt::impl::stylesheet_refcount*>
1005  (pimpl_->xslt_stylesheet_->_private)->inc_ref();
1006 
1007  pimpl_->xslt_stylesheet_ = 0;
1008 }
1009 //####################################################################
1010 void xml::document::set_doc_data_from_xslt (void *data, void *ssheet) {
1011  // this document came from a XSLT transformation
1012  xsltStylesheetPtr ss = static_cast<xsltStylesheetPtr>(ssheet);
1013  pimpl_->set_doc_data(static_cast<xmlDocPtr>(data), false);
1014  pimpl_->xslt_stylesheet_ = ss;
1015  if (ss->_private)
1016  static_cast<xslt::impl::stylesheet_refcount*>
1017  (ss->_private)->inc_ref();
1018 }
1019 //####################################################################
1021  return pimpl_->doc_;
1022 }
1023 //####################################################################
1025  return pimpl_->doc_;
1026 }
1027 //####################################################################
1029  xmlDocPtr xmldoc = pimpl_->doc_;
1030  pimpl_->doc_ = 0;
1031 
1032  return xmldoc;
1033 }
1034 //####################################################################
1035 std::ostream& xml::operator<< (std::ostream &stream, const xml::document &doc) {
1036  doc.save_to_stream(stream, save_op_default);
1037  return stream;
1038 }
1039 //####################################################################
1041  warnings_as_errors_type how) const {
1042  // if there are fatal errors or errors it is a failure
1043  if (messages->has_errors() ||
1044  messages->has_fatal_errors())
1045  return true;
1046  // if there are warnings and they are treated as errors it is a failure
1047  if ((how == type_warnings_are_errors) &&
1048  messages->has_warnings())
1049  return true;
1050  return false;
1051 }
1052 //####################################################################
1053 
1054 namespace {
1055 
1056  // DTD related callbacks
1057  static void register_dtd_error_helper (error_message::message_type mt,
1058  void *v,
1059  const std::string &message) {
1060  try {
1061  error_messages *p = static_cast<error_messages*>(v);
1062  if (p) {
1063  #if LIBXML_VERSION >= 21200
1064  const xmlError * last_err = xmlGetLastError();
1065  long line = 0;
1066  if (last_err)
1067  line = last_err->line;
1068  #else
1069  long line = xmlLastError.line;
1070  #endif
1071  if (line < 0)
1072  line = 0;
1073 
1074  std::string filename;
1075  #if LIBXML_VERSION >= 21200
1076  if (last_err) {
1077  if (last_err->file != NULL) {
1078  filename = last_err->file;
1079  }
1080  }
1081  #else
1082  if (xmlLastError.file != NULL)
1083  filename = xmlLastError.file;
1084  #endif
1085  p->get_messages().push_back(error_message(message, mt,
1086  line, filename));
1087 
1088  #if LIBXML_VERSION >= 21200
1089  xmlResetLastError();
1090  #endif
1091  }
1092  } catch (...) {}
1093  }
1094 
1095  extern "C" void cb_dtd_valid_error (void *v, const char *message, ...) {
1096  std::string temporary;
1097 
1098  va_list ap;
1099  va_start(ap, message);
1100  printf2string(temporary, message, ap);
1101  va_end(ap);
1102 
1103  register_dtd_error_helper(error_message::type_error, v, temporary);
1104  }
1105 
1106  extern "C" void cb_dtd_valid_warning (void *v, const char *message, ...) {
1107  std::string temporary;
1108 
1109  va_list ap;
1110  va_start(ap, message);
1111  printf2string(temporary, message, ap);
1112  va_end(ap);
1113 
1114  register_dtd_error_helper(error_message::type_warning, v, temporary);
1115  }
1116 
1117  // Tree parser related callbacks
1118  static void register_tree_error_helper (error_message::message_type mt,
1119  void *v,
1120  const std::string &message) {
1121  try {
1122  xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(v);
1123  error_messages *p = static_cast<error_messages*>(ctxt->_private);
1124 
1125  // handle bug in older versions of libxml2
1126  if (p) {
1127  #if LIBXML_VERSION >= 21200
1128  const xmlError * last_err = xmlGetLastError();
1129  long line = 0;
1130  if (last_err)
1131  line = last_err->line;
1132  #else
1133  long line = xmlLastError.line;
1134  #endif
1135  if (line < 0)
1136  line = 0;
1137 
1138  std::string filename;
1139  #if LIBXML_VERSION >= 21200
1140  if (last_err) {
1141  if (last_err->file != NULL) {
1142  filename = last_err->file;
1143  }
1144  }
1145  #else
1146  if (xmlLastError.file != NULL)
1147  filename = xmlLastError.file;
1148  #endif
1149  p->get_messages().push_back(error_message(message, mt,
1150  line, filename));
1151 
1152  #if LIBXML_VERSION >= 21200
1153  xmlResetLastError();
1154  #endif
1155  }
1156  } catch (...) {}
1157  }
1158 
1159  extern "C" void cb_tree_parser_fatal_error (void *v,
1160  const char *message, ...) {
1161  std::string temporary;
1162 
1163  va_list ap;
1164  va_start(ap, message);
1165  printf2string(temporary, message, ap);
1166  va_end(ap);
1167 
1168  register_tree_error_helper(error_message::type_fatal_error,
1169  v, temporary);
1170  }
1171 
1172  extern "C" void cb_tree_parser_error (void *v, const char *message, ...) {
1173  std::string temporary;
1174 
1175  va_list ap;
1176  va_start(ap, message);
1177  printf2string(temporary, message, ap);
1178  va_end(ap);
1179 
1180  register_tree_error_helper(error_message::type_error, v, temporary);
1181  }
1182 
1183  extern "C" void cb_tree_parser_warning (void *v, const char *message, ...) {
1184  std::string temporary;
1185 
1186  va_list ap;
1187  va_start(ap, message);
1188  printf2string(temporary, message, ap);
1189  va_end(ap);
1190 
1191  register_tree_error_helper(error_message::type_warning, v, temporary);
1192  }
1193 
1194  extern "C" void cb_tree_parser_ignore (void*, const xmlChar*, int) {
1195  return;
1196  }
1197 }
1198 
The xml::document_proxy class to be a relay between XSLT results and the document.
void release(void) const
The xml::document class is used to hold the XML tree and various bits of information about it.
Definition: document.hpp:80
bool has_internal_subset(void) const
Test to see if this document has an internal subset.
Definition: document.cpp:603
void set_external_subset(const dtd &dtd_)
Sets the document external subset.
Definition: document.cpp:667
node::iterator insert(const node &n)
Insert a new child node.
Definition: document.cpp:720
const std::string & get_encoding(void) const
Get the XML encoding for this document.
Definition: document.cpp:571
document(void)
Create a new XML document with the default settings.
Definition: document.cpp:225
void save_to_stream(std::ostream &stream, save_option_flags flags=save_op_default) const
Convert the XML document tree into XML text data and then insert it into the given stream.
Definition: document.cpp:922
void set_root_node(const node &n)
Set the root node to the given node.
Definition: document.cpp:549
impl::doc_impl * pimpl_
Definition: document.hpp:770
bool get_is_standalone(void) const
Find out if the current document is a standalone document.
Definition: document.cpp:590
bool has_external_subset(void) const
Test to see if this document has an external subset.
Definition: document.cpp:614
node::iterator erase(node::iterator to_erase)
Erase the node that is pointed to by the given iterator.
Definition: document.cpp:759
const dtd & get_internal_subset(void) const
Provides the DTD data that is declared within the XML document itself.
Definition: document.cpp:607
void set_doc_data(void *data)
Definition: document.cpp:998
virtual ~document(void)
Clean up after an XML document object.
Definition: document.cpp:534
bool process_xinclude(void)
Walk through the document and expand <xi:include> elements.
Definition: document.cpp:598
void swap(document &other)
Swap one xml::document object for another.
Definition: document.cpp:530
void save_to_string(std::string &s, save_option_flags flags=save_op_default) const
Convert the XML document tree into XML text data and place it into the given string.
Definition: document.cpp:775
document & operator=(const document &other)
Copy another document object into this one using the assignment operator.
Definition: document.cpp:501
size_type size(void) const
Returns the number of child nodes of this document.
Definition: document.cpp:683
void set_version(const char *version)
Set the XML version number for this document.
Definition: document.cpp:557
std::size_t size_type
size type
Definition: document.hpp:83
bool save_to_file(const char *filename, save_option_flags flags=save_op_default) const
Convert the XML document tree into XML text data and place it into the given filename.
Definition: document.cpp:959
node::iterator replace(node::iterator old_node, const node &new_node)
Replace the node pointed to by the given iterator with another node.
Definition: document.cpp:744
void set_encoding(const char *encoding)
Set the XML encoding string.
Definition: document.cpp:577
void push_back(const node &child)
Add a child xml::node to this document.
Definition: document.cpp:711
bool is_failure(error_messages *messages, warnings_as_errors_type how) const
Definition: document.cpp:1040
void * release_doc_data(void)
Definition: document.cpp:1028
const dtd & get_external_subset(void) const
Provides the DTD data that is referenced from an external source, such as a file or URL.
Definition: document.cpp:618
const node & get_root_node(void) const
Get a reference to the root node of this document.
Definition: document.cpp:539
void set_doc_data_from_xslt(void *data, void *ssheet)
Definition: document.cpp:1010
const std::string & get_version(void) const
Get the XML version for this document.
Definition: document.cpp:553
node::iterator begin(void)
Get an iterator to the first child node of this document.
Definition: document.cpp:695
document & assign(const document &other)
Copy another document object into this one.
Definition: document.cpp:507
void save_to_string_canonical(std::string &str, canonicalization_option c14n_option, canonicalization_comments_option comments_option, canonicalization_format_option format_option, canonicalization_node_sort_option node_sort_option) const
Convert the XML document tree into XML text data and place it into the given string.
Definition: document.cpp:810
void set_is_standalone(bool sa)
Set the standalone flag.
Definition: document.cpp:594
void * get_doc_data(void)
Definition: document.cpp:1020
node::iterator end(void)
Get an iterator that points one past the last child node for this document.
Definition: document.cpp:703
void * get_doc_data_read_only(void) const
Definition: document.cpp:1024
bool validate(error_messages *messages_=NULL, warnings_as_errors_type how=type_warnings_are_errors) const
Validate this document against the DTD that has been attached to it.
Definition: document.cpp:625
The xml::dtd class represents an XML dtd from a file.
Definition: dtd.hpp:62
bool validate(const document &doc, error_messages *messages, warnings_as_errors_type how=type_warnings_are_errors) const
Validate the given XML document.
Definition: dtd.cpp:125
void * get_raw_pointer(void) const
Definition: dtd.cpp:192
The xml::error_message class is used to store a single error message which may appear while parsing o...
Definition: errors.hpp:50
message_type
A type for different type of errors.
Definition: errors.hpp:53
@ type_fatal_error
fatal error
Definition: errors.hpp:54
@ type_warning
warning
Definition: errors.hpp:56
@ type_error
error
Definition: errors.hpp:55
The xml::error_messages class is used to store all the error message which are collected while parsin...
Definition: errors.hpp:137
bool has_fatal_errors(void) const
Check if there are fatal errors in the error messages.
Definition: errors.cpp:126
const error_messages_type & get_messages(void) const
Get the error messages.
Definition: errors.cpp:98
bool has_warnings(void) const
Check if there are warnings in the error messages.
Definition: errors.cpp:118
bool has_errors(void) const
Check if there are errors in the error messages.
Definition: errors.cpp:122
This exception class is thrown by xmlwrapp for all runtime XML-related errors along with the xml::par...
Definition: exception.hpp:64
static bool get_load_external_subsets(void)
This member function provides the current value whether or not the XML parser should load external (D...
Definition: xml_init.cpp:169
static bool get_remove_whitespace(void)
This member function provides the current setting of the XML parser which tells whether it should rem...
Definition: xml_init.cpp:131
static bool get_validate_xml(void)
This member function provides the current value whether or not the XML parser should validate every X...
Definition: xml_init.cpp:188
static void remove_whitespace(bool flag)
This member function controls whether or not the XML parser should remove ignorable whitespace around...
Definition: xml_init.cpp:127
static bool get_substitute_entities(void)
This member function provides the current value whether or not the XML parser should substitute entit...
Definition: xml_init.cpp:150
The xml::node::const_iterator provides a way to access children nodes similar to a standard C++ conta...
Definition: node.hpp:746
The xml::node::iterator provides a way to access children nodes similar to a standard C++ container.
Definition: node.hpp:704
void * get_raw_node(void) const
The xml::node class is used to hold information about one XML node.
Definition: node.hpp:106
node_type get_type(void) const
Get this node's "type".
Definition: node.cpp:806
const char * get_name(void) const
Get the name of this xml::node.
Definition: node.cpp:769
void set_node_data(void *data)
Definition: node.cpp:746
void * get_node_data(void) const
Definition: node.cpp:753
@ type_element
XML element such as "<chapter/>".
Definition: node.hpp:113
@ type_comment
XML comment.
Definition: node.hpp:117
The xml::parser_exception class is used to store parsing and validating exception information.
Definition: errors.hpp:214
The xml::schema class represents an XML schema.
Definition: schema.hpp:61
bool validate(const document &doc, error_messages *messages, warnings_as_errors_type how=type_warnings_are_errors) const
Validate the given XML document.
Definition: schema.cpp:104
static uch flags
XML dtd API for XmlWrapp.
#define test(a, b, c, d, e)
Definition: numeric.c:170
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
static const char * str(char *buf, int n)
Definition: stats.c:84
static char tmp[3200]
Definition: utf8.c:42
char data[12]
Definition: iconv.c:80
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
string
Definition: cgiapp.hpp:690
#define NULL
Definition: ncbistd.hpp:225
yy_size_t n
static int c14n_op_to_libxml2_op(xml::canonicalization_option op)
Definition: document.cpp:94
static void remove_comments_recursively(xml::node &n)
Definition: document.cpp:130
static void sort_attributes_recursively(xml::node &n)
Definition: document.cpp:143
static void sort_node_recursively(xml::node &n)
Definition: document.cpp:122
static void sort_namespace_definitions_recursively(xml::node &n)
Definition: document.cpp:151
static xmlDocPtr xmlSAXParseFileWithData_Custom(xmlSAXHandlerPtr sax, const char *filename, void *data)
Definition: document.cpp:237
static const std::size_t const_buffer_size
Definition: document.cpp:420
static void set_parser_context_options(xmlParserCtxtPtr ctxt)
Definition: document.cpp:159
This file contains the definition of the xml::document class.
This file contains the definition of the xml::exception class.
This file contains the definition of the xml::node class.
const string version
version string
Definition: variables.hpp:66
const struct ncbi::grid::netcache::search::fields::SIZE size
int strcmp(const char *str1, const char *str2)
Definition: odbc_utils.hpp:160
xmlNodePtr node_replace(xmlNodePtr old_node, xmlNodePtr new_node)
Replace a node with another one.
Definition: node_manip.cpp:75
xmlNodePtr node_erase(xmlNodePtr to_erase)
Erase a node from the child list, and then free it from memory.
Definition: node_manip.cpp:108
void clear_https_messages(void)
int save_to_string_cb(void *ctx, const char *buf, int len)
Definition: utility.cpp:183
int convert_to_libxml2_save_options(int options)
Definition: utility.cpp:142
void printf2string(std::string &s, const char *message, va_list ap)
Definition: utility.cpp:79
int save_to_stream_cb(void *ctx, const char *buf, int len)
Definition: utility.cpp:177
xmlNodePtr node_insert(xmlNodePtr parent, xmlNodePtr before, xmlNodePtr to_add)
Insert a node somewhere in the child list of a parent node.
Definition: node_manip.cpp:54
void collect_https_messages(xml::error_messages &append_to)
XML library namespace.
Definition: attributes.hpp:57
int save_option_flags
Bitwise save options mask type and a compression level.
Definition: xml_save.hpp:78
std::ostream & operator<<(std::ostream &stream, const document &doc)
Definition: document.cpp:1035
canonicalization_comments_option
Definition: xml_save.hpp:103
@ keep_comments
Definition: xml_save.hpp:104
@ strip_comments
Definition: xml_save.hpp:105
@ save_op_no_format
Do not format save output.
Definition: xml_save.hpp:59
@ save_op_no_decl
Drop the xml declaration.
Definition: xml_save.hpp:60
@ save_op_default
Default is:
Definition: xml_save.hpp:72
canonicalization_option
Canonicalization mode.
Definition: xml_save.hpp:83
@ c14n_1_1
C14N 1.1 spec.
Definition: xml_save.hpp:86
@ c14n_exclusive_1_0
Exclusive C14N 1.0 spec.
Definition: xml_save.hpp:85
@ sort_attr_and_ns
Essentially it is not a canonicalization.
Definition: xml_save.hpp:87
@ c14n_1_0
Origianal C14N 1.0 spec.
Definition: xml_save.hpp:84
@ sort_attr_and_ns_no_decl
Essentially it is not a canonicalization.
Definition: xml_save.hpp:94
warnings_as_errors_type
A type for different approaches to process warnings.
Definition: errors.hpp:259
@ type_warnings_not_errors
Do not treat warnings as errors.
Definition: errors.hpp:261
@ type_warnings_are_errors
Treat warnings as errors.
Definition: errors.hpp:260
int size_t_to_int_conversion(std::size_t value, const std::string &msg)
Definition: utility.cpp:63
canonicalization_format_option
Definition: xml_save.hpp:108
@ with_formatting
Definition: xml_save.hpp:109
@ without_formatting
Definition: xml_save.hpp:110
canonicalization_node_sort_option
Definition: xml_save.hpp:113
@ with_node_sorting
Definition: xml_save.hpp:114
bool is_xml_output_method(xsltStylesheetPtr ss)
Definition: stylesheet.cpp:79
bool save_to_file(xmlDocPtr doc, xsltStylesheetPtr ss, const char *filename, int)
Definition: stylesheet.cpp:118
void save_to_string(xmlDocPtr doc, xsltStylesheetPtr ss, std::string &s)
Definition: stylesheet.cpp:101
Front end for a platform-specific configuration summary.
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:613
This file contains the definition of the xml::node manipulation functions.
static uint8_t * buffer
Definition: pcre2test.c:1016
XML schema API for XmlWrapp.
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
This file contains definition of the xslt::impl::stylesheet_impl class.
else result
Definition: token2.c:20
Modified on Fri Sep 20 14:57:08 2024 by modify_doxy.py rev. 669887