From cf019f6af64053ff67d064775ae96cbd65b111c1 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Tue, 11 Oct 2016 23:16:14 -0400 Subject: [PATCH] move parser parameter into a field, document some methods --- source/detail/xlsx_consumer.cpp | 1289 +++++++++++++++---------------- source/detail/xlsx_consumer.hpp | 179 ++++- 2 files changed, 779 insertions(+), 689 deletions(-) diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index fd815d06..690cc1a3 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -45,50 +45,6 @@ xlnt::datetime w3cdtf_to_datetime(const std::string &string) return result; } -/* -struct EnumClassHash -{ - template - std::size_t operator()(T t) const - { - return static_cast(t); - } -}; -*/ - -xlnt::protection read_protection(xml::parser &parser) -{ - parser.next_expect(xml::parser::event_type::start_element, "protection"); - - xlnt::protection prot; - prot.locked(is_true(parser.attribute("locked"))); - prot.hidden(is_true(parser.attribute("hidden"))); - - parser.next_expect(xml::parser::event_type::end_element, "protection"); - - return prot; -} - -xlnt::alignment read_alignment(xml::parser &parser) -{ - xlnt::alignment align; - - align.wrap(is_true(parser.attribute("wrapText"))); - align.shrink(is_true(parser.attribute("shrinkToFit"))); - - if (parser.attribute_present("vertical")) - { - align.vertical(parser.attribute("vertical")); - } - - if (parser.attribute_present("horizontal")) - { - align.horizontal(parser.attribute("horizontal")); - } - - return align; -} - xlnt::color read_color(xml::parser &parser) { xlnt::color result; @@ -119,232 +75,6 @@ xlnt::color read_color(xml::parser &parser) return result; } -xlnt::font read_font(xml::parser &parser) -{ - static const auto xmlns = xlnt::constants::get_namespace("worksheet"); - - xlnt::font new_font; - - parser.next_expect(xml::parser::event_type::start_element, xmlns, "font"); - parser.content(xml::parser::content_type::complex); - - while (true) - { - if (parser.peek() == xml::parser::event_type::end_element) break; - - parser.next_expect(xml::parser::event_type::start_element); - parser.content(xml::parser::content_type::simple); - - if (parser.name() == "sz") - { - new_font.size(string_to_size_t(parser.attribute("val"))); - } - else if (parser.name() == "name") - { - new_font.name(parser.attribute("val")); - } - else if (parser.name() == "color") - { - new_font.color(read_color(parser)); - } - else if (parser.name() == "family") - { - new_font.family(string_to_size_t(parser.attribute("val"))); - } - else if (parser.name() == "scheme") - { - new_font.scheme(parser.attribute("val")); - } - else if (parser.name() == "b") - { - if (parser.attribute_present("val")) - { - new_font.bold(is_true(parser.attribute("val"))); - } - else - { - new_font.bold(true); - } - } - else if (parser.name() == "strike") - { - if (parser.attribute_present("val")) - { - new_font.strikethrough(is_true(parser.attribute("val"))); - } - else - { - new_font.strikethrough(true); - } - } - else if (parser.name() == "i") - { - if (parser.attribute_present("val")) - { - new_font.italic(is_true(parser.attribute("val"))); - } - else - { - new_font.italic(true); - } - } - else if (parser.name() == "u") - { - if (parser.attribute_present("val")) - { - new_font.underline(parser.attribute("val")); - } - else - { - new_font.underline(xlnt::font::underline_style::single); - } - } - - parser.next_expect(xml::parser::event_type::end_element); - } - - parser.next_expect(xml::parser::event_type::end_element, xmlns, "font"); - - return new_font; -} - -void read_indexed_colors(xml::parser &parser, std::vector &colors) -{ - colors.clear(); - - while (true) - { - if (parser.peek() == xml::parser::event_type::end_element) - { - break; - } - - colors.push_back(read_color(parser)); - } - - parser.next_expect(xml::parser::event_type::end_element, "indexedColors"); -} - -xlnt::fill read_fill(xml::parser &parser) -{ - static const auto xmlns = xlnt::constants::get_namespace("worksheet"); - - xlnt::fill new_fill; - - parser.next_expect(xml::parser::event_type::start_element, xmlns, "fill"); - parser.content(xml::parser::content_type::complex); - parser.next_expect(xml::parser::event_type::start_element); - - if (parser.qname() == xml::qname(xmlns, "patternFill")) - { - xlnt::pattern_fill pattern; - - if (parser.attribute_present("patternType")) - { - pattern.type(parser.attribute("patternType")); - - while (true) - { - if (parser.peek() == xml::parser::event_type::end_element) - { - break; - } - - parser.next_expect(xml::parser::event_type::start_element); - - if (parser.name() == "fgColor") - { - pattern.foreground(read_color(parser)); - } - else if (parser.name() == "bgColor") - { - pattern.background(read_color(parser)); - } - - parser.next_expect(xml::parser::event_type::end_element); - } - } - - new_fill = pattern; - } - else if (parser.qname() == xml::qname(xmlns, "gradientFill")) - { - xlnt::gradient_fill gradient; - - if (parser.attribute_present("type")) - { - gradient.type(parser.attribute("type")); - } - else - { - gradient.type(xlnt::gradient_fill_type::linear); - } - - while (true) - { - if (parser.peek() == xml::parser::event_type::end_element) break; - - parser.next_expect(xml::parser::event_type::start_element, "stop"); - auto position = parser.attribute("position"); - parser.next_expect(xml::parser::event_type::start_element, "color"); - auto color = read_color(parser); - parser.next_expect(xml::parser::event_type::end_element, "color"); - parser.next_expect(xml::parser::event_type::end_element, "stop"); - - gradient.add_stop(position, color); - } - - new_fill = gradient; - } - - parser.next_expect(xml::parser::event_type::end_element); // or - parser.next_expect(xml::parser::event_type::end_element); // - - return new_fill; -} - -xlnt::border::border_property read_side(xml::parser &parser) -{ - xlnt::border::border_property new_side; - - if (parser.attribute_present("style")) - { - new_side.style(parser.attribute("style")); - } - - if (parser.peek() == xml::parser::event_type::start_element) - { - parser.next_expect(xml::parser::event_type::start_element, "color"); - new_side.color(read_color(parser)); - parser.next_expect(xml::parser::event_type::end_element, "color"); - } - - return new_side; -} - -xlnt::border read_border(xml::parser &parser) -{ - xlnt::border new_border; - - parser.next_expect(xml::parser::event_type::start_element); // - parser.content(xml::parser::content_type::complex); - - while (true) - { - if (parser.peek() == xml::parser::event_type::end_element) break; - - parser.next_expect(xml::parser::event_type::start_element); - auto side_type = xml::value_traits::parse(parser.name(), parser); - auto side = read_side(parser); - new_border.side(side_type, side); - parser.next_expect(xml::parser::event_type::end_element); - } - - parser.next_expect(xml::parser::event_type::end_element); // - - return new_border; -} - std::vector read_relationships(const xlnt::path &part, xlnt::zip_file &archive) { std::vector relationships; @@ -390,82 +120,100 @@ void check_document_type(const std::string &document_content_type) namespace xlnt { namespace detail { -xlsx_consumer::xlsx_consumer(workbook &destination) : destination_(destination) +xlsx_consumer::xlsx_consumer(workbook &target) + : target_(target), + parser_(nullptr) { } void xlsx_consumer::read(const path &source) { - destination_.clear(); source_.load(source); populate_workbook(); } void xlsx_consumer::read(std::istream &source) { - destination_.clear(); source_.load(source); populate_workbook(); } void xlsx_consumer::read(const std::vector &source) { - destination_.clear(); source_.load(source); populate_workbook(); } -// Part Writing Methods +xml::parser &xlsx_consumer::parser() +{ + return *parser_; +} void xlsx_consumer::populate_workbook() { - auto &manifest = destination_.get_manifest(); + target_.clear(); + + auto &manifest = target_.get_manifest(); read_manifest(); for (const auto &rel : manifest.get_relationships(path("/"))) { std::istringstream parser_stream(source_.read(rel.get_target().get_path())); xml::parser parser(parser_stream, rel.get_target().get_path().string()); + parser_ = &parser; switch (rel.get_type()) { case relationship::type::core_properties: - read_core_properties(parser); + read_core_properties(); break; + case relationship::type::extended_properties: - read_extended_properties(parser); + read_extended_properties(); break; + case relationship::type::custom_properties: - read_custom_property(parser); + read_custom_property(); break; + case relationship::type::office_document: check_document_type(manifest.get_content_type(rel.get_target().get_path())); - read_workbook(parser); + read_workbook(); break; + case relationship::type::connections: - read_connections(parser); + read_connections(); break; + case relationship::type::custom_xml_mappings: - read_custom_xml_mappings(parser); + read_custom_xml_mappings(); break; + case relationship::type::external_workbook_references: - read_external_workbook_references(parser); + read_external_workbook_references(); break; + case relationship::type::metadata: - read_metadata(parser); + read_metadata(); break; + case relationship::type::pivot_table: - read_pivot_table(parser); + read_pivot_table(); break; + case relationship::type::shared_workbook_revision_headers: - read_shared_workbook_revision_headers(parser); + read_shared_workbook_revision_headers(); break; + case relationship::type::volatile_dependencies: - read_volatile_dependencies(parser); + read_volatile_dependencies(); break; + default: break; } + + parser_ = nullptr; } const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document); @@ -480,21 +228,27 @@ void xlsx_consumer::populate_workbook() auto receive = xml::parser::receive_default | (using_namespaces ? xml::parser::receive_namespace_decls : 0); xml::parser parser(parser_stream, rel.get_target().get_path().string(), receive); + parser_ = &parser; switch (rel.get_type()) { case relationship::type::shared_string_table: - read_shared_string_table(parser); + read_shared_string_table(); break; + case relationship::type::styles: - read_stylesheet(parser); + read_stylesheet(); break; + case relationship::type::theme: - read_theme(parser); + read_theme(); break; + default: break; } + + parser_ = nullptr; } // Second pass, read sheets themselves @@ -505,21 +259,27 @@ void xlsx_consumer::populate_workbook() std::istringstream parser_stream(source_.read(part_path)); auto receive = xml::parser::receive_default | xml::parser::receive_namespace_decls; xml::parser parser(parser_stream, rel.get_target().get_path().string(), receive); + parser_ = &parser; switch (rel.get_type()) { case relationship::type::chartsheet: - read_chartsheet(rel.get_id(), parser); + read_chartsheet(rel.get_id()); break; + case relationship::type::dialogsheet: - read_dialogsheet(rel.get_id(), parser); + read_dialogsheet(rel.get_id()); break; + case relationship::type::worksheet: - read_worksheet(rel.get_id(), parser); + read_worksheet(rel.get_id()); break; + default: break; } + + parser_ = nullptr; } // Unknown Parts @@ -533,13 +293,18 @@ void xlsx_consumer::populate_workbook() void xlsx_consumer::read_manifest() { path package_rels_path("_rels/.rels"); - if (!source_.has_file(package_rels_path)) throw invalid_file("missing package rels"); + + if (!source_.has_file(package_rels_path)) + { + throw invalid_file("missing package rels"); + } + auto package_rels = read_relationships(package_rels_path, source_); std::istringstream parser_stream(source_.read(path("[Content_Types].xml"))); xml::parser parser(parser_stream, "[Content_Types].xml"); - auto &manifest = destination_.get_manifest(); + auto &manifest = target_.get_manifest(); static const auto xmlns = constants::get_namespace("content-types"); @@ -599,91 +364,91 @@ void xlsx_consumer::read_manifest() } } -void xlsx_consumer::read_extended_properties(xml::parser &parser) +void xlsx_consumer::read_extended_properties() { static const auto xmlns = constants::get_namespace("extended-properties"); static const auto xmlns_vt = constants::get_namespace("vt"); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "Properties"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties"); + parser().content(xml::parser::content_type::complex); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - auto name = parser.name(); + auto name = parser().name(); auto text = std::string(); - while (parser.peek() == xml::parser::event_type::characters) + while (parser().peek() == xml::parser::event_type::characters) { - parser.next_expect(xml::parser::event_type::characters); - text.append(parser.value()); + parser().next_expect(xml::parser::event_type::characters); + text.append(parser().value()); } - if (name == "Application") destination_.set_application(text); - else if (name == "DocSecurity") destination_.set_doc_security(std::stoi(text)); - else if (name == "ScaleCrop") destination_.set_scale_crop(is_true(text)); - else if (name == "Company") destination_.set_company(text); - else if (name == "SharedDoc") destination_.set_shared_doc(is_true(text)); - else if (name == "HyperlinksChanged") destination_.set_hyperlinks_changed(is_true(text)); - else if (name == "AppVersion") destination_.set_app_version(text); - else if (name == "Application") destination_.set_application(text); + if (name == "Application") target_.set_application(text); + else if (name == "DocSecurity") target_.set_doc_security(std::stoi(text)); + else if (name == "ScaleCrop") target_.set_scale_crop(is_true(text)); + else if (name == "Company") target_.set_company(text); + else if (name == "SharedDoc") target_.set_shared_doc(is_true(text)); + else if (name == "HyperlinksChanged") target_.set_hyperlinks_changed(is_true(text)); + else if (name == "AppVersion") target_.set_app_version(text); + else if (name == "Application") target_.set_application(text); else if (name == "HeadingPairs") { - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector"); + parser().content(xml::parser::content_type::complex); - parser.attribute("size"); - parser.attribute("baseType"); + parser().attribute("size"); + parser().attribute("baseType"); - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant"); - parser.content(xml::parser::content_type::complex); - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr"); - parser.next_expect(xml::parser::event_type::characters); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant"); - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant"); - parser.content(xml::parser::content_type::complex); - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "i4"); - parser.next_expect(xml::parser::event_type::characters); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "i4"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant"); + parser().content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr"); + parser().next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant"); + parser().content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "i4"); + parser().next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "i4"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector"); } else if (name == "TitlesOfParts") { - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector"); + parser().content(xml::parser::content_type::complex); - parser.attribute("size"); - parser.attribute("baseType"); + parser().attribute("size"); + parser().attribute("baseType"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr"); - parser.content(xml::parser::content_type::simple); - parser.next_expect(xml::parser::event_type::characters); - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr"); + parser().content(xml::parser::content_type::simple); + parser().next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr"); } - parser.next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector"); } - while (parser.peek() == xml::parser::event_type::characters) + while (parser().peek() == xml::parser::event_type::characters) { - parser.next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::characters); } - parser.next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); } } -void xlsx_consumer::read_core_properties(xml::parser &parser) +void xlsx_consumer::read_core_properties() { static const auto xmlns_cp = constants::get_namespace("core-properties"); static const auto xmlns_dc = constants::get_namespace("dc"); @@ -691,48 +456,48 @@ void xlsx_consumer::read_core_properties(xml::parser &parser) static const auto xmlns_dcmitype = constants::get_namespace("dcmitype"); static const auto xmlns_xsi = constants::get_namespace("xsi"); - parser.next_expect(xml::parser::event_type::start_element, xmlns_cp, "coreProperties"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns_cp, "coreProperties"); + parser().content(xml::parser::content_type::complex); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::characters); - if (parser.namespace_() == xmlns_dc && parser.name() == "creator") + if (parser().namespace_() == xmlns_dc && parser().name() == "creator") { - destination_.set_creator(parser.value()); + target_.set_creator(parser().value()); } - else if (parser.namespace_() == xmlns_cp && parser.name() == "lastModifiedBy") + else if (parser().namespace_() == xmlns_cp && parser().name() == "lastModifiedBy") { - destination_.set_last_modified_by(parser.value()); + target_.set_last_modified_by(parser().value()); } - else if (parser.namespace_() == xmlns_dcterms && parser.name() == "created") + else if (parser().namespace_() == xmlns_dcterms && parser().name() == "created") { - parser.attribute(xml::qname(xmlns_xsi, "type")); - destination_.set_created(w3cdtf_to_datetime(parser.value())); + parser().attribute(xml::qname(xmlns_xsi, "type")); + target_.set_created(w3cdtf_to_datetime(parser().value())); } - else if (parser.namespace_() == xmlns_dcterms && parser.name() == "modified") + else if (parser().namespace_() == xmlns_dcterms && parser().name() == "modified") { - parser.attribute(xml::qname(xmlns_xsi, "type")); - destination_.set_modified(w3cdtf_to_datetime(parser.value())); + parser().attribute(xml::qname(xmlns_xsi, "type")); + target_.set_modified(w3cdtf_to_datetime(parser().value())); } - parser.next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); } - parser.next_expect(xml::parser::event_type::end_element, xmlns_cp, "coreProperties"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_cp, "coreProperties"); } -void xlsx_consumer::read_custom_file_properties(xml::parser &/*parser*/) +void xlsx_consumer::read_custom_file_properties() { } // Write SpreadsheetML-Specific Package Parts -void xlsx_consumer::read_workbook(xml::parser &parser) +void xlsx_consumer::read_workbook() { static const auto xmlns = constants::get_namespace("workbook"); static const auto xmlns_mc = constants::get_namespace("mc"); @@ -741,85 +506,85 @@ void xlsx_consumer::read_workbook(xml::parser &parser) static const auto xmlns_s = constants::get_namespace("worksheet"); static const auto xmlns_x15ac = constants::get_namespace("x15ac"); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "workbook"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbook"); + parser().content(xml::parser::content_type::complex); - while (parser.peek() == xml::parser::event_type::start_namespace_decl) + while (parser().peek() == xml::parser::event_type::start_namespace_decl) { - parser.next_expect(xml::parser::event_type::start_namespace_decl); - if (parser.name() == "x15") destination_.enable_x15(); - parser.next_expect(xml::parser::event_type::end_namespace_decl); + parser().next_expect(xml::parser::event_type::start_namespace_decl); + if (parser().name() == "x15") target_.enable_x15(); + parser().next_expect(xml::parser::event_type::end_namespace_decl); } - if (parser.attribute_present(xml::qname(xmlns_mc, "Ignorable"))) + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { - parser.attribute(xml::qname(xmlns_mc, "Ignorable")); + parser().attribute(xml::qname(xmlns_mc, "Ignorable")); } while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element); + parser().content(xml::parser::content_type::complex); - auto qname = parser.qname(); + auto qname = parser().qname(); if (qname == xml::qname(xmlns, "fileVersion")) { - destination_.d_->has_file_version_ = true; - destination_.d_->file_version_.app_name = parser.attribute("appName"); - destination_.d_->file_version_.last_edited = string_to_size_t(parser.attribute("lastEdited")); - destination_.d_->file_version_.lowest_edited = string_to_size_t(parser.attribute("lowestEdited")); - destination_.d_->file_version_.rup_build = string_to_size_t(parser.attribute("rupBuild")); + target_.d_->has_file_version_ = true; + target_.d_->file_version_.app_name = parser().attribute("appName"); + target_.d_->file_version_.last_edited = string_to_size_t(parser().attribute("lastEdited")); + target_.d_->file_version_.lowest_edited = string_to_size_t(parser().attribute("lowestEdited")); + target_.d_->file_version_.rup_build = string_to_size_t(parser().attribute("rupBuild")); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "fileVersion"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "fileVersion"); } else if (qname == xml::qname(xmlns_mc, "AlternateContent")) { - parser.next_expect(xml::parser::event_type::start_element, xmlns_mc, "Choice"); - parser.content(xml::parser::content_type::complex); - parser.attribute("Requires"); - parser.next_expect(xml::parser::event_type::start_element, xmlns_x15ac, "absPath"); - destination_.set_absolute_path(path(parser.attribute("url"))); - parser.next_expect(xml::parser::event_type::end_element, xmlns_x15ac, "absPath"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_mc, "Choice"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_mc, "AlternateContent"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_mc, "Choice"); + parser().content(xml::parser::content_type::complex); + parser().attribute("Requires"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_x15ac, "absPath"); + target_.set_absolute_path(path(parser().attribute("url"))); + parser().next_expect(xml::parser::event_type::end_element, xmlns_x15ac, "absPath"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "Choice"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "AlternateContent"); } else if (qname == xml::qname(xmlns, "bookViews")) { - if (parser.peek() == xml::parser::event_type::start_element) + if (parser().peek() == xml::parser::event_type::start_element) { - parser.next_expect(xml::parser::event_type::start_element, xmlns, "workbookView"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbookView"); workbook_view view; - view.x_window = string_to_size_t(parser.attribute("xWindow")); - view.y_window = string_to_size_t(parser.attribute("yWindow")); - view.window_width = string_to_size_t(parser.attribute("windowWidth")); - view.window_height = string_to_size_t(parser.attribute("windowHeight")); - view.tab_ratio = string_to_size_t(parser.attribute("tabRatio")); - destination_.set_view(view); + view.x_window = string_to_size_t(parser().attribute("xWindow")); + view.y_window = string_to_size_t(parser().attribute("yWindow")); + view.window_width = string_to_size_t(parser().attribute("windowWidth")); + view.window_height = string_to_size_t(parser().attribute("windowHeight")); + view.tab_ratio = string_to_size_t(parser().attribute("tabRatio")); + target_.set_view(view); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "workbookView"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookView"); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "bookViews"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "bookViews"); } else if (qname == xml::qname(xmlns, "workbookPr")) { - destination_.d_->has_properties_ = true; + target_.d_->has_properties_ = true; - if (parser.attribute_present("date1904")) + if (parser().attribute_present("date1904")) { - const auto value = parser.attribute("date1904"); + const auto value = parser().attribute("date1904"); if (value == "1" || value == "true") { - destination_.set_base_date(xlnt::calendar::mac_1904); + target_.set_base_date(xlnt::calendar::mac_1904); } } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "workbookPr"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookPr"); } else if (qname == xml::qname(xmlns, "sheets")) { @@ -827,155 +592,155 @@ void xlsx_consumer::read_workbook(xml::parser &parser) while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns_s, "sheet"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_s, "sheet"); - std::string rel_id(parser.attribute(xml::qname(xmlns_r, "id"))); - std::string title(parser.attribute("name")); - auto id = string_to_size_t(parser.attribute("sheetId")); + std::string rel_id(parser().attribute(xml::qname(xmlns_r, "id"))); + std::string title(parser().attribute("name")); + auto id = string_to_size_t(parser().attribute("sheetId")); sheet_title_id_map_[title] = id; sheet_title_index_map_[title] = index++; - destination_.d_->sheet_title_rel_id_map_[title] = rel_id; + target_.d_->sheet_title_rel_id_map_[title] = rel_id; - parser.next_expect(xml::parser::event_type::end_element, xmlns_s, "sheet"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_s, "sheet"); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "sheets"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheets"); } else if (qname == xml::qname(xmlns, "calcPr")) { - destination_.d_->has_calculation_properties_ = true; - parser.attribute("calcId"); - parser.attribute("concurrentCalc"); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "calcPr"); + target_.d_->has_calculation_properties_ = true; + parser().attribute("calcId"); + parser().attribute("concurrentCalc"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "calcPr"); } else if (qname == xml::qname(xmlns, "extLst")) { - parser.next_expect(xml::parser::event_type::start_element, xmlns, "ext"); - parser.content(xml::parser::content_type::complex); - parser.attribute("uri"); - parser.next_expect(xml::parser::event_type::start_element, xmlns_mx, "ArchID"); - destination_.d_->has_arch_id_ = true; - parser.attribute("Flags"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_mx, "ArchID"); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "ext"); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "extLst"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext"); + parser().content(xml::parser::content_type::complex); + parser().attribute("uri"); + parser().next_expect(xml::parser::event_type::start_element, xmlns_mx, "ArchID"); + target_.d_->has_arch_id_ = true; + parser().attribute("Flags"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_mx, "ArchID"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "extLst"); } } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "workbook"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbook"); } // Write Workbook Relationship Target Parts -void xlsx_consumer::read_calculation_chain(xml::parser &/*parser*/) +void xlsx_consumer::read_calculation_chain() { } -void xlsx_consumer::read_chartsheet(const std::string &/*title*/, xml::parser &/*parser*/) +void xlsx_consumer::read_chartsheet(const std::string &/*title*/) { } -void xlsx_consumer::read_connections(xml::parser &/*parser*/) +void xlsx_consumer::read_connections() { } -void xlsx_consumer::read_custom_property(xml::parser &/*parser*/) +void xlsx_consumer::read_custom_property() { } -void xlsx_consumer::read_custom_xml_mappings(xml::parser &/*parser*/) +void xlsx_consumer::read_custom_xml_mappings() { } -void xlsx_consumer::read_dialogsheet(const std::string &/*title*/, xml::parser &/*parser*/) +void xlsx_consumer::read_dialogsheet(const std::string &/*title*/) { } -void xlsx_consumer::read_external_workbook_references(xml::parser &/*parser*/) +void xlsx_consumer::read_external_workbook_references() { } -void xlsx_consumer::read_metadata(xml::parser &/*parser*/) +void xlsx_consumer::read_metadata() { } -void xlsx_consumer::read_pivot_table(xml::parser &/*parser*/) +void xlsx_consumer::read_pivot_table() { } -void xlsx_consumer::read_shared_string_table(xml::parser &parser) +void xlsx_consumer::read_shared_string_table() { static const auto xmlns = constants::get_namespace("shared-strings"); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "sst"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "sst"); std::size_t unique_count = 0; - if (parser.attribute_present("uniqueCount")) + if (parser().attribute_present("uniqueCount")) { - unique_count = string_to_size_t(parser.attribute("uniqueCount")); + unique_count = string_to_size_t(parser().attribute("uniqueCount")); } - auto &strings = destination_.get_shared_strings(); + auto &strings = target_.get_shared_strings(); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "si"); - parser.next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "si"); + parser().next_expect(xml::parser::event_type::start_element); text t; - if (parser.name() == "t") + if (parser().name() == "t") { - t.set_plain_string(parser.value()); + t.set_plain_string(parser().value()); } - else if (parser.name() == "r") // possible multiple text entities. + else if (parser().name() == "r") // possible multiple text entities. { while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "t"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "t"); text_run run; - run.set_string(parser.value()); + run.set_string(parser().value()); - if (parser.peek() == xml::parser::event_type::start_element) + if (parser().peek() == xml::parser::event_type::start_element) { - parser.next_expect(xml::parser::event_type::start_element, xmlns, "rPr"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "rPr"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - if (parser.qname() == xml::qname(xmlns, "sz")) + if (parser().qname() == xml::qname(xmlns, "sz")) { - run.set_size(string_to_size_t(parser.attribute("val"))); + run.set_size(string_to_size_t(parser().attribute("val"))); } - else if (parser.qname() == xml::qname(xmlns, "rFont")) + else if (parser().qname() == xml::qname(xmlns, "rFont")) { - run.set_font(parser.attribute("val")); + run.set_font(parser().attribute("val")); } - else if (parser.qname() == xml::qname(xmlns, "color")) + else if (parser().qname() == xml::qname(xmlns, "color")) { - run.set_color(parser.attribute("rgb")); + run.set_color(parser().attribute("rgb")); } - else if (parser.qname() == xml::qname(xmlns, "family")) + else if (parser().qname() == xml::qname(xmlns, "family")) { - run.set_family(string_to_size_t(parser.attribute("val"))); + run.set_family(string_to_size_t(parser().attribute("val"))); } - else if (parser.qname() == xml::qname(xmlns, "scheme")) + else if (parser().qname() == xml::qname(xmlns, "scheme")) { - run.set_scheme(parser.attribute("val")); + run.set_scheme(parser().attribute("val")); } - parser.next_expect(xml::parser::event_type::end_element, parser.qname()); + parser().next_expect(xml::parser::event_type::end_element, parser().qname()); } } @@ -992,45 +757,45 @@ void xlsx_consumer::read_shared_string_table(xml::parser &parser) } } -void xlsx_consumer::read_shared_workbook_revision_headers(xml::parser &/*parser*/) +void xlsx_consumer::read_shared_workbook_revision_headers() { } -void xlsx_consumer::read_shared_workbook(xml::parser &/*parser*/) +void xlsx_consumer::read_shared_workbook() { } -void xlsx_consumer::read_shared_workbook_user_data(xml::parser &/*parser*/) +void xlsx_consumer::read_shared_workbook_user_data() { } -void xlsx_consumer::read_stylesheet(xml::parser &parser) +void xlsx_consumer::read_stylesheet() { static const auto xmlns = constants::get_namespace("worksheet"); static const auto xmlns_mc = constants::get_namespace("mc"); static const auto xmlns_x14 = constants::get_namespace("x14"); static const auto xmlns_x14ac = constants::get_namespace("x14ac"); - auto &stylesheet = destination_.impl().stylesheet_; + auto &stylesheet = target_.impl().stylesheet_; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "styleSheet"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "styleSheet"); + parser().content(xml::parser::content_type::complex); while (true) { - if (parser.peek() != xml::parser::event_type::start_namespace_decl) break; + if (parser().peek() != xml::parser::event_type::start_namespace_decl) break; - parser.next_expect(xml::parser::event_type::start_namespace_decl); + parser().next_expect(xml::parser::event_type::start_namespace_decl); - if (parser.namespace_() == xmlns_x14ac) + if (parser().namespace_() == xmlns_x14ac) { - destination_.enable_x15(); + target_.enable_x15(); } } - if (parser.attribute_present(xml::qname(xmlns_mc, "Ignorable"))) + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { - parser.attribute(xml::qname(xmlns_mc, "Ignorable")); + parser().attribute(xml::qname(xmlns_mc, "Ignorable")); } struct formatting_record @@ -1057,21 +822,52 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element); + parser().content(xml::parser::content_type::complex); - if (parser.qname() == xml::qname(xmlns, "borders")) + if (parser().qname() == xml::qname(xmlns, "borders")) { stylesheet.borders.clear(); - auto count = parser.attribute("count"); + auto count = parser().attribute("count"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; - stylesheet.borders.push_back(read_border(parser)); + if (parser().peek() == xml::parser::event_type::end_element) break; + + stylesheet.borders.push_back(xlnt::border()); + auto &border = stylesheet.borders.back(); + + parser().next_expect(xml::parser::event_type::start_element); // + parser().content(xml::parser::content_type::complex); + + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; + + parser().next_expect(xml::parser::event_type::start_element); + auto side_type = xml::value_traits::parse(parser().name(), parser()); + xlnt::border::border_property side; + + if (parser().attribute_present("style")) + { + side.style(parser().attribute("style")); + } + + if (parser().peek() == xml::parser::event_type::start_element) + { + parser().next_expect(xml::parser::event_type::start_element, "color"); + side.color(read_color(parser())); + parser().next_expect(xml::parser::event_type::end_element, "color"); + } + + border.side(side_type, side); + parser().next_expect(xml::parser::event_type::end_element); + } + + parser().next_expect(xml::parser::event_type::end_element); // } if (count != stylesheet.borders.size()) @@ -1079,16 +875,87 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "fills")) + else if (parser().qname() == xml::qname(xmlns, "fills")) { stylesheet.fills.clear(); - auto count = parser.attribute("count"); + auto count = parser().attribute("count"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; - stylesheet.fills.push_back(read_fill(parser)); + if (parser().peek() == xml::parser::event_type::end_element) break; + + stylesheet.fills.push_back(xlnt::fill()); + auto &new_fill = stylesheet.fills.back(); + + parser().next_expect(xml::parser::event_type::start_element, xmlns, "fill"); + parser().content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element); + + if (parser().qname() == xml::qname(xmlns, "patternFill")) + { + xlnt::pattern_fill pattern; + + if (parser().attribute_present("patternType")) + { + pattern.type(parser().attribute("patternType")); + + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) + { + break; + } + + parser().next_expect(xml::parser::event_type::start_element); + + if (parser().name() == "fgColor") + { + pattern.foreground(read_color(parser())); + } + else if (parser().name() == "bgColor") + { + pattern.background(read_color(parser())); + } + + parser().next_expect(xml::parser::event_type::end_element); + } + } + + new_fill = pattern; + } + else if (parser().qname() == xml::qname(xmlns, "gradientFill")) + { + xlnt::gradient_fill gradient; + + if (parser().attribute_present("type")) + { + gradient.type(parser().attribute("type")); + } + else + { + gradient.type(xlnt::gradient_fill_type::linear); + } + + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; + + parser().next_expect(xml::parser::event_type::start_element, "stop"); + auto position = parser().attribute("position"); + parser().next_expect(xml::parser::event_type::start_element, "color"); + auto color = read_color(parser()); + parser().next_expect(xml::parser::event_type::end_element, "color"); + parser().next_expect(xml::parser::event_type::end_element, "stop"); + + gradient.add_stop(position, color); + } + + new_fill = gradient; + } + + parser().next_expect(xml::parser::event_type::end_element); // or + parser().next_expect(xml::parser::event_type::end_element); // } if (count != stylesheet.fills.size()) @@ -1096,21 +963,103 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "fonts")) + else if (parser().qname() == xml::qname(xmlns, "fonts")) { stylesheet.fonts.clear(); - auto count = parser.attribute("count"); + auto count = parser().attribute("count"); - if (parser.attribute_present(xml::qname(xmlns_x14ac, "knownFonts"))) + if (parser().attribute_present(xml::qname(xmlns_x14ac, "knownFonts"))) { - parser.attribute(xml::qname(xmlns_x14ac, "knownFonts")); + parser().attribute(xml::qname(xmlns_x14ac, "knownFonts")); } while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; - stylesheet.fonts.push_back(read_font(parser)); + if (parser().peek() == xml::parser::event_type::end_element) break; + + stylesheet.fonts.push_back(xlnt::font()); + auto &new_font = stylesheet.fonts.back(); + + parser().next_expect(xml::parser::event_type::start_element, xmlns, "font"); + parser().content(xml::parser::content_type::complex); + + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; + + parser().next_expect(xml::parser::event_type::start_element); + parser().content(xml::parser::content_type::simple); + + if (parser().name() == "sz") + { + new_font.size(string_to_size_t(parser().attribute("val"))); + } + else if (parser().name() == "name") + { + new_font.name(parser().attribute("val")); + } + else if (parser().name() == "color") + { + new_font.color(read_color(parser())); + } + else if (parser().name() == "family") + { + new_font.family(string_to_size_t(parser().attribute("val"))); + } + else if (parser().name() == "scheme") + { + new_font.scheme(parser().attribute("val")); + } + else if (parser().name() == "b") + { + if (parser().attribute_present("val")) + { + new_font.bold(is_true(parser().attribute("val"))); + } + else + { + new_font.bold(true); + } + } + else if (parser().name() == "strike") + { + if (parser().attribute_present("val")) + { + new_font.strikethrough(is_true(parser().attribute("val"))); + } + else + { + new_font.strikethrough(true); + } + } + else if (parser().name() == "i") + { + if (parser().attribute_present("val")) + { + new_font.italic(is_true(parser().attribute("val"))); + } + else + { + new_font.italic(true); + } + } + else if (parser().name() == "u") + { + if (parser().attribute_present("val")) + { + new_font.underline(parser().attribute("val")); + } + else + { + new_font.underline(xlnt::font::underline_style::single); + } + } + + parser().next_expect(xml::parser::event_type::end_element); + } + + parser().next_expect(xml::parser::event_type::end_element, xmlns, "font"); } if (count != stylesheet.fonts.size()) @@ -1118,16 +1067,16 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "numFmts")) + else if (parser().qname() == xml::qname(xmlns, "numFmts")) { stylesheet.number_formats.clear(); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, "numFmt"); - auto format_string = parser.attribute("formatCode"); + parser().next_expect(xml::parser::event_type::start_element, "numFmt"); + auto format_string = parser().attribute("formatCode"); if (format_string == "GENERAL") { @@ -1137,29 +1086,29 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) xlnt::number_format nf; nf.set_format_string(format_string); - nf.set_id(string_to_size_t(parser.attribute("numFmtId"))); + nf.set_id(string_to_size_t(parser().attribute("numFmtId"))); stylesheet.number_formats.push_back(nf); } } - else if (parser.qname() == xml::qname(xmlns, "colors")) + else if (parser().qname() == xml::qname(xmlns, "colors")) { } - else if (parser.qname() == xml::qname(xmlns, "cellStyles")) + else if (parser().qname() == xml::qname(xmlns, "cellStyles")) { - auto count = parser.attribute("count"); + auto count = parser().attribute("count"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; auto &data = *style_datas.emplace(style_datas.end()); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "cellStyle"); - data.name = parser.attribute("name"); - data.record_id = parser.attribute("xfId"); - data.builtin_id = parser.attribute("builtinId"); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "cellStyle"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "cellStyle"); + data.name = parser().attribute("name"); + data.record_id = parser().attribute("xfId"); + data.builtin_id = parser().attribute("builtinId"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "cellStyle"); } if (count != style_datas.size()) @@ -1167,82 +1116,100 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "cellStyleXfs") - || parser.qname() == xml::qname(xmlns, "cellXfs")) + else if (parser().qname() == xml::qname(xmlns, "cellStyleXfs") + || parser().qname() == xml::qname(xmlns, "cellXfs")) { - auto in_style_records = parser.name() == "cellStyleXfs"; - auto count = parser.attribute("count"); + auto in_style_records = parser().name() == "cellStyleXfs"; + auto count = parser().attribute("count"); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "xf"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "xf"); auto &record = *(!in_style_records ? format_records.emplace(format_records.end()) : style_records.emplace(style_records.end())); - auto apply_alignment_present = parser.attribute_present("applyAlignment"); + auto apply_alignment_present = parser().attribute_present("applyAlignment"); auto alignment_applied = apply_alignment_present - && is_true(parser.attribute("applyAlignment")); + && is_true(parser().attribute("applyAlignment")); record.alignment.second = alignment_applied; - auto border_applied = parser.attribute_present("applyBorder") - && is_true(parser.attribute("applyBorder")); - auto border_index = parser.attribute_present("borderId") - ? string_to_size_t(parser.attribute("borderId")) : 0; + auto border_applied = parser().attribute_present("applyBorder") + && is_true(parser().attribute("applyBorder")); + auto border_index = parser().attribute_present("borderId") + ? string_to_size_t(parser().attribute("borderId")) : 0; record.border_id = { border_index, border_applied }; - auto fill_applied = parser.attribute_present("applyFill") - && is_true(parser.attribute("applyFill")); - auto fill_index = parser.attribute_present("fillId") - ? string_to_size_t(parser.attribute("fillId")) : 0; + auto fill_applied = parser().attribute_present("applyFill") + && is_true(parser().attribute("applyFill")); + auto fill_index = parser().attribute_present("fillId") + ? string_to_size_t(parser().attribute("fillId")) : 0; record.fill_id = { fill_index, fill_applied }; - auto font_applied = parser.attribute_present("applyFont") - && is_true(parser.attribute("applyFont")); - auto font_index = parser.attribute_present("fontId") - ? string_to_size_t(parser.attribute("fontId")) : 0; + auto font_applied = parser().attribute_present("applyFont") + && is_true(parser().attribute("applyFont")); + auto font_index = parser().attribute_present("fontId") + ? string_to_size_t(parser().attribute("fontId")) : 0; record.font_id = { font_index, font_applied }; - auto number_format_applied = parser.attribute_present("applyNumberFormat") - && is_true(parser.attribute("applyNumberFormat")); - auto number_format_id = parser.attribute_present("numFmtId") - ? string_to_size_t(parser.attribute("numFmtId")) : 0; + auto number_format_applied = parser().attribute_present("applyNumberFormat") + && is_true(parser().attribute("applyNumberFormat")); + auto number_format_id = parser().attribute_present("numFmtId") + ? string_to_size_t(parser().attribute("numFmtId")) : 0; record.number_format_id = { number_format_id, number_format_applied }; - auto apply_protection_present = parser.attribute_present("applyProtection"); + auto apply_protection_present = parser().attribute_present("applyProtection"); auto protection_applied = apply_protection_present - && is_true(parser.attribute("applyProtection")); + && is_true(parser().attribute("applyProtection")); record.protection.second = protection_applied; - if (parser.attribute_present("xfId") && parser.name() == "cellXfs") + if (parser().attribute_present("xfId") && parser().name() == "cellXfs") { - record.style_id = { parser.attribute("xfId"), true }; + record.style_id = { parser().attribute("xfId"), true }; } while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - if (parser.qname() == xml::qname(xmlns, "alignment")) + if (parser().qname() == xml::qname(xmlns, "alignment")) { - record.alignment.first = read_alignment(parser); + record.alignment.first.wrap(is_true(parser().attribute("wrapText"))); + record.alignment.first.shrink(is_true(parser().attribute("shrinkToFit"))); + + if (parser().attribute_present("vertical")) + { + record.alignment.first.vertical( + parser().attribute("vertical")); + } + + if (parser().attribute_present("horizontal")) + { + record.alignment.first.horizontal( + parser().attribute("horizontal")); + } + record.alignment.second = !apply_alignment_present || alignment_applied; } - else if (parser.qname() == xml::qname(xmlns, "protection")) + else if (parser().qname() == xml::qname(xmlns, "protection")) { - record.protection.first = read_protection(parser); + parser().next_expect(xml::parser::event_type::start_element, "protection"); + record.protection.first.locked(is_true(parser().attribute("locked"))); + record.protection.first.hidden(is_true(parser().attribute("hidden"))); + parser().next_expect(xml::parser::event_type::end_element, "protection"); + record.protection.second = !apply_protection_present || protection_applied; } - parser.next_expect(xml::parser::event_type::end_element, parser.qname()); + parser().next_expect(xml::parser::event_type::end_element, parser().qname()); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "xf"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "xf"); } @@ -1252,16 +1219,16 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "dxfs")) + else if (parser().qname() == xml::qname(xmlns, "dxfs")) { - auto count = parser.attribute("count"); + auto count = parser().attribute("count"); std::size_t processed = 0; while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.next_expect(xml::parser::event_type::end_element); + if (parser().peek() == xml::parser::event_type::end_element) break; + parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::end_element); } if (count != processed) @@ -1269,18 +1236,18 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "tableStyles")) + else if (parser().qname() == xml::qname(xmlns, "tableStyles")) { - auto default_table_style = parser.attribute("defaultTableStyle"); - auto default_pivot_style = parser.attribute("defaultPivotStyle"); - auto count = parser.attribute("count"); + auto default_table_style = parser().attribute("defaultTableStyle"); + auto default_pivot_style = parser().attribute("defaultPivotStyle"); + auto count = parser().attribute("count"); std::size_t processed = 0; while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.next_expect(xml::parser::event_type::end_element); + if (parser().peek() == xml::parser::event_type::end_element) break; + parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::end_element); } if (count != processed) @@ -1288,23 +1255,23 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) throw xlnt::exception("counts don't match"); } } - else if (parser.qname() == xml::qname(xmlns, "extLst")) + else if (parser().qname() == xml::qname(xmlns, "extLst")) { - parser.next_expect(xml::parser::event_type::start_element, xmlns, "ext"); - parser.content(xml::parser::content_type::complex); - parser.attribute("uri"); - parser.next_expect(xml::parser::event_type::start_namespace_decl); - parser.next_expect(xml::parser::event_type::start_element, xmlns_x14, "slicerStyles"); - parser.attribute("defaultSlicerStyle"); - parser.next_expect(xml::parser::event_type::end_element, xmlns_x14, "slicerStyles"); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "ext"); - parser.next_expect(xml::parser::event_type::end_namespace_decl); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext"); + parser().content(xml::parser::content_type::complex); + parser().attribute("uri"); + parser().next_expect(xml::parser::event_type::start_namespace_decl); + parser().next_expect(xml::parser::event_type::start_element, xmlns_x14, "slicerStyles"); + parser().attribute("defaultSlicerStyle"); + parser().next_expect(xml::parser::event_type::end_element, xmlns_x14, "slicerStyles"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext"); + parser().next_expect(xml::parser::event_type::end_namespace_decl); } - parser.next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "styleSheet"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "styleSheet"); auto lookup_number_format = [&](std::size_t number_format_id) { @@ -1363,23 +1330,23 @@ void xlsx_consumer::read_stylesheet(xml::parser &parser) } } -void xlsx_consumer::read_theme(xml::parser &/*parser*/) +void xlsx_consumer::read_theme() { - destination_.set_theme(theme()); + target_.set_theme(theme()); } -void xlsx_consumer::read_volatile_dependencies(xml::parser &/*parser*/) +void xlsx_consumer::read_volatile_dependencies() { } -void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parser) +void xlsx_consumer::read_worksheet(const std::string &rel_id) { static const auto xmlns = constants::get_namespace("worksheet"); static const auto xmlns_mc = constants::get_namespace("mc"); static const auto xmlns_x14ac = constants::get_namespace("x14ac"); - auto title = std::find_if(destination_.d_->sheet_title_rel_id_map_.begin(), - destination_.d_->sheet_title_rel_id_map_.end(), + auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(), + target_.d_->sheet_title_rel_id_map_.end(), [&](const std::pair &p) { return p.second == rel_id; @@ -1388,93 +1355,93 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse auto id = sheet_title_id_map_[title]; auto index = sheet_title_index_map_[title]; - auto insertion_iter = destination_.d_->worksheets_.begin(); - while (insertion_iter != destination_.d_->worksheets_.end() + auto insertion_iter = target_.d_->worksheets_.begin(); + while (insertion_iter != target_.d_->worksheets_.end() && sheet_title_index_map_[insertion_iter->title_] < index) { ++insertion_iter; } - destination_.d_->worksheets_.emplace(insertion_iter, &destination_, id, title); + target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title); - auto ws = destination_.get_sheet_by_id(id); + auto ws = target_.get_sheet_by_id(id); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "worksheet"); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "worksheet"); + parser().content(xml::parser::content_type::complex); - while (parser.peek() == xml::parser::event_type::start_namespace_decl) + while (parser().peek() == xml::parser::event_type::start_namespace_decl) { - parser.next_expect(xml::parser::event_type::start_namespace_decl); + parser().next_expect(xml::parser::event_type::start_namespace_decl); - if (parser.namespace_() == xmlns_x14ac) + if (parser().namespace_() == xmlns_x14ac) { ws.enable_x14ac(); } } - if (parser.attribute_present(xml::qname(xmlns_mc, "Ignorable"))) + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { - parser.attribute(xml::qname(xmlns_mc, "Ignorable")); + parser().attribute(xml::qname(xmlns_mc, "Ignorable")); } xlnt::range_reference full_range; while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); - parser.content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element); + parser().content(xml::parser::content_type::complex); - if (parser.qname() == xml::qname(xmlns, "dimension")) + if (parser().qname() == xml::qname(xmlns, "dimension")) { - full_range = xlnt::range_reference(parser.attribute("ref")); + full_range = xlnt::range_reference(parser().attribute("ref")); ws.d_->has_dimension_ = true; - parser.next_expect(xml::parser::event_type::end_element, xmlns, "dimension"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "dimension"); } - else if (parser.qname() == xml::qname(xmlns, "sheetViews")) + else if (parser().qname() == xml::qname(xmlns, "sheetViews")) { ws.d_->has_view_ = true; while (true) { - parser.attribute_map(); + parser().attribute_map(); - if (parser.next() == xml::parser::event_type::end_element && parser.name() == "sheetViews") + if (parser().next() == xml::parser::event_type::end_element && parser().name() == "sheetViews") { break; } } - //parser.next_expect(xml::parser::event_type::end_element, xmlns, "sheetViews"); + //parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetViews"); } - else if (parser.qname() == xml::qname(xmlns, "sheetFormatPr")) + else if (parser().qname() == xml::qname(xmlns, "sheetFormatPr")) { ws.d_->has_format_properties_ = true; while (true) { - parser.attribute_map(); + parser().attribute_map(); - if (parser.next() == xml::parser::event_type::end_element && parser.name() == "sheetFormatPr") + if (parser().next() == xml::parser::event_type::end_element && parser().name() == "sheetFormatPr") { break; } } - //parser.next_expect(xml::parser::event_type::end_element, xmlns, "sheetFormatPr"); + //parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetFormatPr"); } - else if (parser.qname() == xml::qname(xmlns, "mergeCells")) + else if (parser().qname() == xml::qname(xmlns, "mergeCells")) { - auto count = std::stoull(parser.attribute("count")); + auto count = std::stoull(parser().attribute("count")); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell"); - ws.merge_cells(range_reference(parser.attribute("ref"))); - parser.next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell"); + ws.merge_cells(range_reference(parser().attribute("ref"))); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "mergeCell"); count--; } @@ -1484,26 +1451,26 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse throw invalid_file("sizes don't match"); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "mergeCells"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "mergeCells"); } - else if (parser.qname() == xml::qname(xmlns, "sheetData")) + else if (parser().qname() == xml::qname(xmlns, "sheetData")) { - auto &shared_strings = destination_.get_shared_strings(); + auto &shared_strings = target_.get_shared_strings(); while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "row"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "row"); - auto row_index = static_cast(std::stoull(parser.attribute("r"))); + auto row_index = static_cast(std::stoull(parser().attribute("r"))); - if (parser.attribute_present("ht")) + if (parser().attribute_present("ht")) { - ws.get_row_properties(row_index).height = std::stold(parser.attribute("ht")); + ws.get_row_properties(row_index).height = std::stold(parser().attribute("ht")); } - std::string span_string = parser.attribute("spans"); + std::string span_string = parser().attribute("spans"); auto colon_index = span_string.find(':'); column_t min_column = 0; @@ -1522,16 +1489,16 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "c"); - auto cell = ws.get_cell(cell_reference(parser.attribute("r"))); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "c"); + auto cell = ws.get_cell(cell_reference(parser().attribute("r"))); - auto has_type = parser.attribute_present("t"); - auto type = has_type ? parser.attribute("t") : ""; + auto has_type = parser().attribute_present("t"); + auto type = has_type ? parser().attribute("t") : ""; - auto has_format = parser.attribute_present("s"); - auto format_id = static_cast(has_format ? std::stoull(parser.attribute("s")) : 0LL); + auto has_format = parser().attribute_present("s"); + auto format_id = static_cast(has_format ? std::stoull(parser().attribute("s")) : 0LL); auto has_value = false; auto value_string = std::string(); @@ -1542,29 +1509,29 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - if (parser.qname() == xml::qname(xmlns, "v")) + if (parser().qname() == xml::qname(xmlns, "v")) { has_value = true; - value_string = parser.value(); + value_string = parser().value(); } - else if (parser.qname() == xml::qname(xmlns, "f")) + else if (parser().qname() == xml::qname(xmlns, "f")) { has_formula = true; - has_shared_formula = parser.attribute_present("t") && parser.attribute("t") == "shared"; - formula_value_string = parser.value(); + has_shared_formula = parser().attribute_present("t") && parser().attribute("t") == "shared"; + formula_value_string = parser().value(); } - else if (parser.qname() == xml::qname(xmlns, "is")) + else if (parser().qname() == xml::qname(xmlns, "is")) { - parser.next_expect(xml::parser::event_type::start_element, xmlns, "t"); - value_string = parser.value(); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "t"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "t"); + value_string = parser().value(); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "t"); } - parser.next_expect(xml::parser::event_type::end_element, parser.qname()); + parser().next_expect(xml::parser::event_type::end_element, parser().qname()); } if (has_formula && !has_shared_formula && !ws.get_workbook().get_data_only()) @@ -1600,28 +1567,28 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse if (has_format) { - cell.set_format(destination_.get_format(format_id)); + cell.set_format(target_.get_format(format_id)); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "c"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "c"); } } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "sheetData"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetData"); } - else if (parser.qname() == xml::qname(xmlns, "cols")) + else if (parser().qname() == xml::qname(xmlns, "cols")) { while (true) { - if (parser.peek() == xml::parser::event_type::end_element) break; + if (parser().peek() == xml::parser::event_type::end_element) break; - parser.next_expect(xml::parser::event_type::start_element, xmlns, "col"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "col"); - auto min = static_cast(std::stoull(parser.attribute("min"))); - auto max = static_cast(std::stoull(parser.attribute("max"))); - auto width = std::stold(parser.attribute("width")); - bool custom = parser.attribute("customWidth") == std::string("1"); - auto column_style = static_cast(parser.attribute_present("style") ? std::stoull(parser.attribute("style")) : 0); + auto min = static_cast(std::stoull(parser().attribute("min"))); + auto max = static_cast(std::stoull(parser().attribute("max"))); + auto width = std::stold(parser().attribute("width")); + bool custom = parser().attribute("customWidth") == std::string("1"); + auto column_style = static_cast(parser().attribute_present("style") ? std::stoull(parser().attribute("style")) : 0); for (auto column = min; column <= max; column++) { @@ -1635,53 +1602,53 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id, xml::parser &parse ws.get_column_properties(min).custom = custom; } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "col"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "col"); } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "cols"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "cols"); } - else if (parser.qname() == xml::qname(xmlns, "autoFilter")) + else if (parser().qname() == xml::qname(xmlns, "autoFilter")) { - ws.auto_filter(xlnt::range_reference(parser.attribute("ref"))); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "autoFilter"); + ws.auto_filter(xlnt::range_reference(parser().attribute("ref"))); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "autoFilter"); } - else if (parser.qname() == xml::qname(xmlns, "pageMargins")) + else if (parser().qname() == xml::qname(xmlns, "pageMargins")) { page_margins margins; - margins.set_top(parser.attribute("top")); - margins.set_bottom(parser.attribute("bottom")); - margins.set_left(parser.attribute("left")); - margins.set_right(parser.attribute("right")); - margins.set_header(parser.attribute("header")); - margins.set_footer(parser.attribute("footer")); + margins.set_top(parser().attribute("top")); + margins.set_bottom(parser().attribute("bottom")); + margins.set_left(parser().attribute("left")); + margins.set_right(parser().attribute("right")); + margins.set_header(parser().attribute("header")); + margins.set_footer(parser().attribute("footer")); ws.set_page_margins(margins); - parser.next_expect(xml::parser::event_type::end_element, xmlns, "pageMargins"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "pageMargins"); } } - parser.next_expect(xml::parser::event_type::end_element, xmlns, "worksheet"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "worksheet"); } // Sheet Relationship Target Parts -void xlsx_consumer::read_comments(xml::parser &/*parser*/) +void xlsx_consumer::read_comments() { } -void xlsx_consumer::read_drawings(xml::parser &/*parser*/) +void xlsx_consumer::read_drawings() { } // Unknown Parts -void xlsx_consumer::read_unknown_parts(xml::parser &/*parser*/) +void xlsx_consumer::read_unknown_parts() { } -void xlsx_consumer::read_unknown_relationships(xml::parser &/*parser*/) +void xlsx_consumer::read_unknown_relationships() { } diff --git a/source/detail/xlsx_consumer.hpp b/source/detail/xlsx_consumer.hpp index abce4e41..f1bb2636 100644 --- a/source/detail/xlsx_consumer.hpp +++ b/source/detail/xlsx_consumer.hpp @@ -63,6 +63,17 @@ public: #endif private: + /// + /// Ignore all remaining elements at the same depth in the current XML parser. + /// + void skip_remaining_elements(); + + /// + /// Convenience method to dereference the pointer to the current parser to avoid + /// having to use "parser_->" constantly. + /// + xml::parser &parser(); + /// /// Read all the files needed from the XLSX archive and initialize all of /// the data in the workbook to match. @@ -71,60 +82,172 @@ private: // Package Parts + /// + /// Parse content types ([Content_Types].xml) and package relationships (_rels/.rels). + /// void read_manifest(); - void read_core_properties(xml::parser &parser); - void read_extended_properties(xml::parser &parser); - void read_custom_file_properties(xml::parser &parser); + /// + /// Parse the core properties about the current package (usually docProps/core.xml). + /// + void read_core_properties(); + + /// + /// Parse extra application-speicific package properties (usually docProps/app.xml). + void read_extended_properties(); + + /// + /// Parse custom file properties. These aren't associated with a particular application + /// but extensions to OOXML can use this part to hold extra data about the package. + /// + void read_custom_file_properties(); // SpreadsheetML-Specific Package Parts - void read_workbook(xml::parser &parser); + /// + /// Parse the main XML document about the workbook and then all child relationships + /// of the workbook (e.g. worksheets). + /// + void read_workbook(); // Workbook Relationship Target Parts - void read_calculation_chain(xml::parser &parser); - void read_connections(xml::parser &parser); - void read_custom_property(xml::parser &parser); - void read_custom_xml_mappings(xml::parser &parser); - void read_external_workbook_references(xml::parser &parser); - void read_metadata(xml::parser &parser); - void read_pivot_table(xml::parser &parser); - void read_shared_string_table(xml::parser &parser); - void read_shared_workbook_revision_headers(xml::parser &parser); - void read_shared_workbook(xml::parser &parser); - void read_shared_workbook_user_data(xml::parser &parser); - void read_stylesheet(xml::parser &parser); - void read_theme(xml::parser &parser); - void read_volatile_dependencies(xml::parser &parser); + /// + /// xl/calcChain.xml + /// + void read_calculation_chain(); - void read_chartsheet(const std::string &title, xml::parser &parser); - void read_dialogsheet(const std::string &title, xml::parser &parser); - void read_worksheet(const std::string &title, xml::parser &parser); + /// + /// + /// + void read_connections(); + + /// + /// + /// + void read_custom_property(); + + /// + /// + /// + void read_custom_xml_mappings(); + + /// + /// + /// + void read_external_workbook_references(); + + /// + /// + /// + void read_metadata(); + + /// + /// + /// + void read_pivot_table(); + + /// + /// xl/sharedStrings.xml + /// + void read_shared_string_table(); + + /// + /// + /// + void read_shared_workbook_revision_headers(); + + /// + /// + /// + void read_shared_workbook(); + + /// + /// + /// + void read_shared_workbook_user_data(); + + /// + /// xl/styles.xml + /// + void read_stylesheet(); + + /// + /// xl/theme/theme1.xml + /// + void read_theme(); + + /// + /// + /// + void read_volatile_dependencies(); + + /// + /// xl/sheets/*.xml + /// + void read_chartsheet(const std::string &title); + + /// + /// xl/sheets/*.xml + /// + void read_dialogsheet(const std::string &title); + + /// + /// xl/sheets/*.xml + /// + void read_worksheet(const std::string &title); // Sheet Relationship Target Parts - void read_comments(xml::parser &parser); - void read_drawings(xml::parser &parser); + /// + /// + /// + void read_comments(); + + /// + /// + /// + void read_drawings(); // Unknown Parts - void read_unknown_parts(xml::parser &parser); - void read_unknown_relationships(xml::parser &parser); + /// + /// + /// + void read_unknown_parts(); /// - /// A reference to the archive from which files representing the workbook - /// are read. + /// + /// + void read_unknown_relationships(); + + /// + /// The ZIP file containing the files that make up the OOXML package. /// zip_file source_; + /// + /// Map of sheet titles to relationship IDs. + /// std::unordered_map sheet_title_id_map_; + + /// + /// Map of sheet titles to indices. Used to ensure sheets are maintained + /// in the correct order. + /// std::unordered_map sheet_title_index_map_; /// /// A reference to the workbook which is being read. /// - workbook &destination_; + workbook &target_; + + /// + /// This pointer is generally set by instantiating an xml::parser in a function + /// scope and then calling a read_*() method which uses xlsx_consumer::parser() + /// to access the object. + /// + xml::parser *parser_; }; } // namespace detail