Declaration nodes improvements (they now automatically get name "xml", they can't be inserted as a non-document child, document saving prints declaration only if there is none present in the document)
git-svn-id: http://pugixml.googlecode.com/svn/trunk@517 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
1a007d66e6
commit
a562014cc2
3 changed files with 126 additions and 11 deletions
|
@ -2902,6 +2902,28 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
inline bool has_declaration(const xml_node& node)
|
||||
{
|
||||
for (xml_node child = node.first_child(); child; child = child.next_sibling())
|
||||
{
|
||||
xml_node_type type = child.type();
|
||||
|
||||
if (type == node_declaration) return true;
|
||||
if (type == node_element) return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool allow_insert_child(xml_node_type parent, xml_node_type child)
|
||||
{
|
||||
if (parent != node_document && parent != node_element) return false;
|
||||
if (child == node_document || child == node_null) return false;
|
||||
if (parent != node_document && child == node_declaration) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void recursive_copy_skip(xml_node& dest, const xml_node& source, const xml_node& skip)
|
||||
{
|
||||
assert(dest.type() == source.type());
|
||||
|
@ -3491,9 +3513,11 @@ namespace pugi
|
|||
|
||||
xml_node xml_node::root() const
|
||||
{
|
||||
xml_node r = *this;
|
||||
while (r && r.parent()) r = r.parent();
|
||||
return r;
|
||||
xml_node_struct* r = _root;
|
||||
|
||||
while (r && r->parent) r = r->parent;
|
||||
|
||||
return xml_node(r);
|
||||
}
|
||||
|
||||
const char_t* xml_node::child_value() const
|
||||
|
@ -3673,15 +3697,19 @@ namespace pugi
|
|||
|
||||
xml_node xml_node::append_child(xml_node_type type)
|
||||
{
|
||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||
if (!allow_insert_child(this->type(), type)) return xml_node();
|
||||
|
||||
return xml_node(append_node(_root, get_allocator(_root), type));
|
||||
xml_node n(append_node(_root, get_allocator(_root), type));
|
||||
|
||||
if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node)
|
||||
{
|
||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||
if (node.parent() != *this) return xml_node();
|
||||
if (!allow_insert_child(this->type(), type)) return xml_node();
|
||||
if (!node._root || node._root->parent != _root) return xml_node();
|
||||
|
||||
xml_node n(allocate_node(get_allocator(_root), type));
|
||||
n._root->parent = _root;
|
||||
|
@ -3695,13 +3723,15 @@ namespace pugi
|
|||
n._root->next_sibling = node._root;
|
||||
node._root->prev_sibling_c = n._root;
|
||||
|
||||
if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
xml_node xml_node::insert_child_after(xml_node_type type, const xml_node& node)
|
||||
{
|
||||
if ((this->type() != node_element && this->type() != node_document) || type == node_document || type == node_null) return xml_node();
|
||||
if (node.parent() != *this) return xml_node();
|
||||
if (!allow_insert_child(this->type(), type)) return xml_node();
|
||||
if (!node._root || node._root->parent != _root) return xml_node();
|
||||
|
||||
xml_node n(allocate_node(get_allocator(_root), type));
|
||||
n._root->parent = _root;
|
||||
|
@ -3715,6 +3745,8 @@ namespace pugi
|
|||
n._root->prev_sibling_c = node._root;
|
||||
node._root->next_sibling = n._root;
|
||||
|
||||
if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -3777,7 +3809,7 @@ namespace pugi
|
|||
|
||||
void xml_node::remove_child(const xml_node& n)
|
||||
{
|
||||
if (!_root || n.parent() != *this) return;
|
||||
if (!_root || !n._root || n._root->parent != _root) return;
|
||||
|
||||
if (n._root->next_sibling) n._root->next_sibling->prev_sibling_c = n._root->prev_sibling_c;
|
||||
else if (_root->first_child) _root->first_child->prev_sibling_c = n._root->prev_sibling_c;
|
||||
|
@ -4385,7 +4417,7 @@ namespace pugi
|
|||
|
||||
xml_buffered_writer buffered_writer(writer, encoding);
|
||||
|
||||
if (!(flags & format_no_declaration))
|
||||
if (!(flags & format_no_declaration) && !has_declaration(*this))
|
||||
{
|
||||
buffered_writer.write(PUGIXML_TEXT("<?xml version=\"1.0\"?>"));
|
||||
if (!(flags & format_raw)) buffered_writer.write('\n');
|
||||
|
|
|
@ -211,6 +211,41 @@ TEST_XML(document_save_declaration, "<node/>")
|
|||
CHECK(writer.as_string() == STR("<?xml version=\"1.0\"?>\n<node />\n"));
|
||||
}
|
||||
|
||||
TEST_XML(document_save_declaration_present_first, "<node/>")
|
||||
{
|
||||
doc.insert_child_before(node_declaration, doc.first_child()).append_attribute(STR("encoding")) = STR("utf8");
|
||||
|
||||
xml_writer_string writer;
|
||||
|
||||
doc.save(writer, STR(""), pugi::format_default, get_native_encoding());
|
||||
|
||||
CHECK(writer.as_string() == STR("<?xml encoding=\"utf8\"?>\n<node />\n"));
|
||||
}
|
||||
|
||||
TEST_XML(document_save_declaration_present_second, "<node/>")
|
||||
{
|
||||
doc.insert_child_before(node_declaration, doc.first_child()).append_attribute(STR("encoding")) = STR("utf8");
|
||||
doc.insert_child_before(node_comment, doc.first_child()).set_value(STR("text"));
|
||||
|
||||
xml_writer_string writer;
|
||||
|
||||
doc.save(writer, STR(""), pugi::format_default, get_native_encoding());
|
||||
|
||||
CHECK(writer.as_string() == STR("<!--text-->\n<?xml encoding=\"utf8\"?>\n<node />\n"));
|
||||
}
|
||||
|
||||
TEST_XML(document_save_declaration_present_last, "<node/>")
|
||||
{
|
||||
doc.append_child(node_declaration).append_attribute(STR("encoding")) = STR("utf8");
|
||||
|
||||
xml_writer_string writer;
|
||||
|
||||
doc.save(writer, STR(""), pugi::format_default, get_native_encoding());
|
||||
|
||||
// node writer only looks for declaration before the first element child
|
||||
CHECK(writer.as_string() == STR("<?xml version=\"1.0\"?>\n<node />\n<?xml encoding=\"utf8\"?>\n"));
|
||||
}
|
||||
|
||||
TEST_XML(document_save_file, "<node/>")
|
||||
{
|
||||
#ifdef __unix
|
||||
|
|
|
@ -532,3 +532,51 @@ TEST_XML(dom_attr_assign_large_number, "<node attr1='' attr2='' />")
|
|||
CHECK(test_node(node, STR("<node attr1=\"3.40282e+038\" attr2=\"1.79769e+308\" />"), STR(""), pugi::format_raw) ||
|
||||
test_node(node, STR("<node attr1=\"3.40282e+38\" attr2=\"1.79769e+308\" />"), STR(""), pugi::format_raw));
|
||||
}
|
||||
|
||||
TEST(dom_node_declaration_name)
|
||||
{
|
||||
xml_document doc;
|
||||
doc.append_child(node_declaration);
|
||||
|
||||
// name 'xml' is auto-assigned
|
||||
CHECK(doc.first_child().type() == node_declaration);
|
||||
CHECK_STRING(doc.first_child().name(), STR("xml"));
|
||||
|
||||
doc.insert_child_after(node_declaration, doc.first_child());
|
||||
doc.insert_child_before(node_declaration, doc.first_child());
|
||||
|
||||
CHECK_NODE(doc, STR("<?xml?><?xml?><?xml?>"));
|
||||
}
|
||||
|
||||
TEST(dom_node_declaration_top_level)
|
||||
{
|
||||
xml_document doc;
|
||||
doc.append_child().set_name(STR("node"));
|
||||
|
||||
xml_node node = doc.first_child();
|
||||
node.append_child(node_pcdata).set_value(STR("text"));
|
||||
|
||||
CHECK(node.insert_child_before(node_declaration, node.first_child()) == xml_node());
|
||||
CHECK(node.insert_child_after(node_declaration, node.first_child()) == xml_node());
|
||||
CHECK(node.append_child(node_declaration) == xml_node());
|
||||
|
||||
CHECK_NODE(doc, STR("<node>text</node>"));
|
||||
|
||||
CHECK(doc.insert_child_before(node_declaration, node));
|
||||
CHECK(doc.insert_child_after(node_declaration, node));
|
||||
CHECK(doc.append_child(node_declaration));
|
||||
|
||||
CHECK_NODE(doc, STR("<?xml?><node>text</node><?xml?><?xml?>"));
|
||||
}
|
||||
|
||||
TEST(dom_node_declaration_copy)
|
||||
{
|
||||
xml_document doc;
|
||||
doc.append_child(node_declaration);
|
||||
|
||||
doc.append_child().set_name(STR("node"));
|
||||
|
||||
doc.last_child().append_copy(doc.first_child());
|
||||
|
||||
CHECK_NODE(doc, STR("<?xml?><node />"));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue