bool xml_document::to_string(buffer& buf, bool pretty_print, const struct node* node, unsigned depth) const { do { if (pretty_print) { // If not the first node... if (node != _M_nodes) { if (!buf.append("\r\n", 2)) { return false; } } } if (!node_to_string(buf, pretty_print, node, depth)) { return false; } if (node->child != -1) { if (!to_string(buf, pretty_print, &(_M_nodes[node->child]), depth + 1)) { return false; } if (pretty_print) { if (!buf.append("\r\n", 2)) { return false; } for (unsigned i = 0; i < depth; i++) { if (!buf.append('\t')) { return false; } } } if (!buf.format("</%.*s>", node->len, _M_buf.data() + node->text)) { return false; } } if (node->next < 0) { return true; } node = &(_M_nodes[node->next]); } while (true); }
bool xml_document::node_to_string(buffer& buf, bool pretty_print, const struct node* node, unsigned depth) const { if (pretty_print) { for (unsigned i = 0; i < depth; i++) { if (!buf.append('\t')) { return false; } } } switch (node->type) { case DOCTYPE_NODE: return buf.format("<!DOCTYPE %.*s>", node->len, _M_buf.data() + node->text); case PROCESSING_INSTRUCTION_NODE: return buf.format("<?%.*s?>", node->len, _M_buf.data() + node->text); case COMMENT_NODE: return buf.format("<!-- %.*s -->", node->len, _M_buf.data() + node->text); case ELEMENT_NODE: if (!buf.format("<%.*s", node->len, _M_buf.data() + node->text)) { return false; } if (node->attributes) { const char* name; size_t namelen; const char* value; size_t valuelen; for (size_t i = 0; node->attributes->get(i, name, namelen, value, valuelen); i++) { char quotes = (memchr(value, '"', valuelen)) ? '\'' : '"'; if (!buf.format(" %.*s=%c%.*s%c", namelen, name, quotes, valuelen, value, quotes)) { return false; } } } if (node->child > 0) { return buf.append('>'); } else { return buf.append("/>", 2); } case TEXT_NODE: return buf.format("%.*s", node->len, _M_buf.data() + node->text); default: return false; } }