diff --git a/src/xml-cxx/xml.hxx b/src/xml-cxx/xml.hxx index c6afa8e..27a43c2 100644 --- a/src/xml-cxx/xml.hxx +++ b/src/xml-cxx/xml.hxx @@ -189,13 +189,6 @@ namespace xml { stream_error("missing end tag, end of file reached", t, is, tag, c) { } }; - class empty_stream: public stream_error { - public: - empty_stream(const Node& t, std::istream& is, const Tag& tag, char c=0) - throw(): - stream_error("no xml tag found, stream is empty", t, is, tag, c) { - } - }; class wrong_start_tag: public stream_error { public: wrong_start_tag(const Node& t, std::istream& is, const Tag& tag, char c=0) @@ -303,7 +296,8 @@ namespace xml { //---------------------------------------------------------------------------- //! An xml Node. /*! XML Nodes may contain either text or other nodes, but not both - at the same time. */ + at the same time. This node can hold other nodes. For a Node for + text contents, see xml::String. */ class Node { private: typedef std::vector Contents; @@ -398,7 +392,7 @@ namespace xml { throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch, second_slash_in_tag, character_after_slash, missing_end_tag, attribute_value_not_quoted, access_error, - empty_stream, duplicate_attribute, attributes_in_end_tag); + duplicate_attribute, attributes_in_end_tag); private: friend class stream_error; Factory(); // not implemented diff --git a/src/xml.cxx b/src/xml.cxx index a6b0505..6cfe109 100644 --- a/src/xml.cxx +++ b/src/xml.cxx @@ -426,15 +426,13 @@ namespace xml { throw(tag_expected, type_mismatch) { std::string::size_type start(txt.find_first_not_of(" \t\n\r")), - last(txt.find_last_of(" \t\n\r")); + last(txt.find_last_not_of(" \t\n\r")); if (start==std::string::npos) { // empty - set to 0 _text = "0"; return *this; } - if (txt.find_first_not_of - ("0123456789", start, - last!=std::string::npos?last-start+1:txt.size()-start) - !=std::string::npos) + std::string::size_type pos(txt.find_first_not_of("0123456789", start)); + if (pos node(_template->clone()); node->clear(); Tag res; - while (true) try { + while (true) { res = tag(is, *node); *node<name()!=res.name) throw wrong_start_tag(*node, is, res); + return read(is, *_template); //! @todo store instead of ignore case SPECIAL: break; } - } catch (missing_end_tag&) { - throw empty_stream(*node, is, res); } } catch (exception& e) { e.line(_line); diff --git a/test/xml_test.cxx b/test/xml_test.cxx index 027f8fe..5d471ac 100644 --- a/test/xml_test.cxx +++ b/test/xml_test.cxx @@ -161,6 +161,106 @@ class StringTest: public CppUnit::TestFixture { }; CPPUNIT_TEST_SUITE_REGISTRATION(StringTest); +class ComplexTest: public CppUnit::TestFixture { + public: + void nodes() { + xml::Factory factory(xml::Node("base") + <<(xml::Node("child").attr("a", xml::optional) + <"<"<"<" + <<"xxx13" + <<" 42 " + <<"" + <<"< otherchild >< / otherchild >< otherchild / >"<"; + std::auto_ptr node(factory.read(file1)); // should work + CPPUNIT_ASSERT_EQUAL((size_t)2, node->list("child").size()); + CPPUNIT_ASSERT_EQUAL((size_t)3, (*node)[0].list("childofchild").size()); + CPPUNIT_ASSERT_EQUAL((size_t)4, (*node)[0].list("number").size()); + CPPUNIT_ASSERT_EQUAL((size_t)0, (*node)[1].list("childofchild").size()); + CPPUNIT_ASSERT_EQUAL((size_t)2, node->list("otherchild").size()); + CPPUNIT_ASSERT_EQUAL(std::string("xxx"), *(*node)["child"][2]); + CPPUNIT_ASSERT_EQUAL(std::string("13"), *(*node)["child"][3]); + CPPUNIT_ASSERT_EQUAL(std::string("0"), *(*node)["child"][4]); + CPPUNIT_ASSERT_EQUAL(std::string("42"), *(*node)["child"][5]); + CPPUNIT_ASSERT_EQUAL(std::string("0"), *(*node)["child"][6]); + std::stringstream file2; + file2<<""<"<"<" + <<"xxx" + <<"" + <<"< otherchild >< / otherchild >< otherchild / >"<"; + CPPUNIT_ASSERT_THROW(factory.read(file2), xml::access_error); + { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::wrong_end_tag); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::wrong_start_tag); + } { + std::stringstream file("base"); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::tag_expected); + } { + std::stringstream file("hallo"); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::tag_expected); + } { + std::stringstream file + ("x"); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::type_mismatch); + } { + std::stringstream file + ("xyz"); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::type_mismatch); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::second_slash_in_tag); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::character_after_slash); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag); + } { + std::stringstream file; + CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), + xml::attribute_value_not_quoted); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::duplicate_attribute); + } { + std::stringstream file(""); + CPPUNIT_ASSERT_THROW(factory.read(file), xml::attributes_in_end_tag); + } + } + void attributes() { + xml::Factory factory(xml::Node("base") + <<(xml::Node("child") + <