// file : xsd/cxx/parser/non-validating/parser.txx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include namespace xsd { namespace cxx { namespace parser { namespace non_validating { // empty_content // template void empty_content:: _start_any_element (const ro_string&, const ro_string&, const ro_string*) { } template void empty_content:: _end_any_element (const ro_string&, const ro_string&) { } template void empty_content:: _any_attribute (const ro_string&, const ro_string&, const ro_string&) { } template void empty_content:: _any_characters (const ro_string&) { } // // template bool empty_content:: _start_element_impl (const ro_string&, const ro_string&, const ro_string*) { return false; } template bool empty_content:: _end_element_impl (const ro_string&, const ro_string&) { return false; } template bool empty_content:: _attribute_impl (const ro_string&, const ro_string&, const ro_string&) { return false; } template bool empty_content:: _characters_impl (const ro_string&) { return false; } template void empty_content:: _start_element (const ro_string& ns, const ro_string& name, const ro_string* type) { if (!_start_element_impl (ns, name, type)) _start_any_element (ns, name, type); } template void empty_content:: _end_element (const ro_string& ns, const ro_string& name) { if (!_end_element_impl (ns, name)) _end_any_element (ns, name); } template void empty_content:: _attribute (const ro_string& ns, const ro_string& name, const ro_string& value) { // Weed out special attributes: xsi:type, xsi:nil, // xsi:schemaLocation and noNamespaceSchemaLocation. // See section 3.2.7 in Structures for details. // if (ns == xml::bits::xsi_namespace () && (name == xml::bits::type () || name == xml::bits::nil () || name == xml::bits::schema_location () || name == xml::bits::no_namespace_schema_location ())) return; // Also some parsers (notably Xerces-C++) supplies us with // namespace-prefix mapping attributes. // if (ns == xml::bits::xmlns_namespace ()) return; if (!_attribute_impl (ns, name, value)) _any_attribute (ns, name, value); } template void empty_content:: _characters (const ro_string& s) { if (!_characters_impl (s)) _any_characters (s); } // simple_content // template void simple_content:: _attribute (const ro_string& ns, const ro_string& name, const ro_string& value) { // Weed out special attributes: xsi:type, xsi:nil, // xsi:schemaLocation and xsi:noNamespaceSchemaLocation. // See section 3.2.7 in Structures for details. // if (ns == xml::bits::xsi_namespace () && (name == xml::bits::type () || name == xml::bits::nil () || name == xml::bits::schema_location () || name == xml::bits::no_namespace_schema_location ())) return; // Also some parsers (notably Xerces-C++) supplies us with // namespace-prefix mapping attributes. // if (ns == xml::bits::xmlns_namespace ()) return; if (!_attribute_impl (ns, name, value)) _any_attribute (ns, name, value); } template void simple_content:: _characters (const ro_string& str) { _characters_impl (str); } // complex_content // template void complex_content:: _start_element (const ro_string& ns, const ro_string& name, const ro_string* type) { state& s (context_.top ()); if (s.depth_++ > 0) { if (s.any_) _start_any_element (ns, name, type); else if (s.parser_) s.parser_->_start_element (ns, name, type); } else { if (!_start_element_impl (ns, name, type)) { _start_any_element (ns, name, type); s.any_ = true; } else if (s.parser_ != 0) s.parser_->_pre_impl (); } } template void complex_content:: _end_element (const ro_string& ns, const ro_string& name) { // To understand what's going on here it is helpful to think of // a "total depth" as being the sum of individual depths over // all elements. // if (context_.top ().depth_ == 0) { state& s (context_.under_top ()); // One before last. if (--s.depth_ > 0) { // Indirect recursion. // if (s.parser_) s.parser_->_end_element (ns, name); } else { // Direct recursion. // assert (this == s.parser_); this->_post_impl (); if (!_end_element_impl (ns, name)) assert (false); } } else { state& s (context_.top ()); if (--s.depth_ > 0) { if (s.any_) _end_any_element (ns, name); else if (s.parser_) s.parser_->_end_element (ns, name); } else { if (s.parser_ != 0 && !s.any_) s.parser_->_post_impl (); if (!_end_element_impl (ns, name)) { s.any_ = false; _end_any_element (ns, name); } } } } template void complex_content:: _attribute (const ro_string& ns, const ro_string& name, const ro_string& value) { // Weed out special attributes: xsi:type, xsi:nil, // xsi:schemaLocation and xsi:noNamespaceSchemaLocation. // See section 3.2.7 in Structures for details. // if (ns == xml::bits::xsi_namespace () && (name == xml::bits::type () || name == xml::bits::nil () || name == xml::bits::schema_location () || name == xml::bits::no_namespace_schema_location ())) return; // Also some parsers (notably Xerces-C++) supplies us with // namespace-prefix mapping attributes. // if (ns == xml::bits::xmlns_namespace ()) return; state& s (context_.top ()); if (s.depth_ > 0) { if (s.any_) _any_attribute (ns, name, value); else if (s.parser_) s.parser_->_attribute (ns, name, value); } else { if (!_attribute_impl (ns, name, value)) _any_attribute (ns, name, value); } } template void complex_content:: _characters (const ro_string& str) { state& s (context_.top ()); if (s.depth_ > 0) { if (s.any_) _any_characters (str); else if (s.parser_) s.parser_->_characters (str); } else { if (!_characters_impl (str)) _any_characters (str); } } template void complex_content:: _pre_impl () { context_.push (state ()); this->_pre (); } template void complex_content:: _post_impl () { this->_post (); context_.pop (); } // list_base // namespace bits { // Find first non-space character. // template typename ro_string::size_type find_ns (const C* s, typename ro_string::size_type size, typename ro_string::size_type pos) { while (pos < size && (s[pos] == C (0x20) || s[pos] == C (0x0A) || s[pos] == C (0x0D) || s[pos] == C (0x09))) ++pos; return pos < size ? pos : ro_string::npos; } // Find first space character. // template typename ro_string::size_type find_s (const C* s, typename ro_string::size_type size, typename ro_string::size_type pos) { while (pos < size && s[pos] != C (0x20) && s[pos] != C (0x0A) && s[pos] != C (0x0D) && s[pos] != C (0x09)) ++pos; return pos < size ? pos : ro_string::npos; } } // Relevant XML Schema Part 2: Datatypes sections: 4.2.1.2, 4.3.6. // template void list_base:: _pre_impl () { simple_content::_pre_impl (); buf_.clear (); } template void list_base:: _characters (const ro_string& s) { typedef typename ro_string::size_type size_type; const C* data (s.data ()); size_type size (s.size ()); // Handle the previous chunk if we start with a ws. // if (!buf_.empty () && (data[0] == C (0x20) || data[0] == C (0x0A) || data[0] == C (0x0D) || data[0] == C (0x09))) { ro_string tmp (buf_); // Private copy ctor. _xsd_parse_item (tmp); buf_.clear (); } // Traverse the data while logically collapsing spaces. // for (size_type i (bits::find_ns (data, size, 0)); i != ro_string::npos;) { size_type j (bits::find_s (data, size, i)); if (j != ro_string::npos) { if (buf_.empty ()) { ro_string tmp (data + i, j - i); // Private copy ctor. _xsd_parse_item (tmp); } else { // Assemble the first item in str from buf_ and s. // std::basic_string str; str.swap (buf_); str.append (data + i, j - i); ro_string tmp (str); // Private copy ctor. _xsd_parse_item (tmp); } i = bits::find_ns (data, size, j); } else { // Last fragment, append it to the buf_. // buf_.append (data + i, size - i); break; } } } template void list_base:: _post_impl () { // Handle the last item. // if (!buf_.empty ()) { ro_string tmp (buf_); // Private copy ctor. _xsd_parse_item (tmp); } simple_content::_post_impl (); } } } } }