From 9ae506c1eaacdd8b8cd7e1af866498f1728fda61 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Sun, 3 Jul 2016 19:22:08 -0400 Subject: [PATCH] move serialization classes to detail, recouple with pugixml (no reason to abstract) --- include/xlnt/serialization/xml_document.hpp | 75 --- include/xlnt/serialization/xml_node.hpp | 80 --- include/xlnt/serialization/xml_serializer.hpp | 46 -- .../{serialization => workbook}/encoding.hpp | 0 include/xlnt/xlnt.hpp | 4 +- source/cell/cell.cpp | 2 +- .../comment_serializer.cpp | 4 +- .../detail}/comment_serializer.hpp | 16 +- .../excel_serializer.cpp | 118 +++-- .../detail}/excel_serializer.hpp | 0 .../manifest_serializer.cpp | 44 +- .../detail}/manifest_serializer.hpp | 9 +- .../relationship_serializer.cpp | 49 +- .../detail}/relationship_serializer.hpp | 0 .../shared_strings_serializer.cpp | 93 ++-- .../detail}/shared_strings_serializer.hpp | 9 +- .../style_serializer.cpp | 498 +++++++++--------- .../detail}/style_serializer.hpp | 10 +- source/detail/theme_serializer.cpp | 370 +++++++++++++ .../detail}/theme_serializer.hpp | 9 +- source/detail/workbook_impl.hpp | 2 +- source/detail/workbook_serializer.cpp | 331 ++++++++++++ .../detail}/workbook_serializer.hpp | 21 +- .../worksheet_serializer.cpp | 325 ++++++------ .../detail}/worksheet_serializer.hpp | 9 +- source/detail/xml_document_impl.hpp | 39 -- source/detail/xml_node_impl.hpp | 44 -- source/packaging/tests/test_core.hpp | 11 +- source/serialization/theme_serializer.cpp | 373 ------------- source/serialization/workbook_serializer.cpp | 350 ------------ source/serialization/xml_document.cpp | 105 ---- source/serialization/xml_node.cpp | 161 ------ source/serialization/xml_serializer.cpp | 62 --- source/styles/tests/test_stylesheet.hpp | 18 +- .../tests/test_read.hpp | 14 +- .../tests/test_style_writer.hpp | 10 +- source/workbook/tests/test_theme.hpp | 10 +- .../tests/test_write.hpp | 102 ++-- .../tests/test_write_workbook.hpp | 49 +- source/workbook/workbook.cpp | 4 +- source/worksheet/tests/test_worksheet.hpp | 1 - tests/helpers/helper.hpp | 71 ++- 42 files changed, 1462 insertions(+), 2086 deletions(-) delete mode 100644 include/xlnt/serialization/xml_document.hpp delete mode 100644 include/xlnt/serialization/xml_node.hpp delete mode 100644 include/xlnt/serialization/xml_serializer.hpp rename include/xlnt/{serialization => workbook}/encoding.hpp (100%) rename source/{serialization => detail}/comment_serializer.cpp (94%) rename {include/xlnt/serialization => source/detail}/comment_serializer.hpp (84%) rename source/{serialization => detail}/excel_serializer.cpp (73%) rename {include/xlnt/serialization => source/detail}/excel_serializer.hpp (100%) rename source/{serialization => detail}/manifest_serializer.cpp (64%) rename {include/xlnt/serialization => source/detail}/manifest_serializer.hpp (91%) rename source/{serialization => detail}/relationship_serializer.cpp (65%) rename {include/xlnt/serialization => source/detail}/relationship_serializer.hpp (100%) rename source/{serialization => detail}/shared_strings_serializer.cpp (54%) rename {include/xlnt/serialization => source/detail}/shared_strings_serializer.hpp (86%) rename source/{serialization => detail}/style_serializer.cpp (58%) rename {include/xlnt/serialization => source/detail}/style_serializer.hpp (94%) create mode 100644 source/detail/theme_serializer.cpp rename {include/xlnt/serialization => source/detail}/theme_serializer.hpp (90%) create mode 100644 source/detail/workbook_serializer.cpp rename {include/xlnt/serialization => source/detail}/workbook_serializer.hpp (79%) rename source/{serialization => detail}/worksheet_serializer.cpp (53%) rename {include/xlnt/serialization => source/detail}/worksheet_serializer.hpp (90%) delete mode 100644 source/detail/xml_document_impl.hpp delete mode 100644 source/detail/xml_node_impl.hpp delete mode 100644 source/serialization/theme_serializer.cpp delete mode 100644 source/serialization/workbook_serializer.cpp delete mode 100644 source/serialization/xml_document.cpp delete mode 100644 source/serialization/xml_node.cpp delete mode 100644 source/serialization/xml_serializer.cpp rename source/{serialization => workbook}/tests/test_read.hpp (98%) rename source/{serialization => workbook}/tests/test_style_writer.hpp (96%) rename source/{serialization => workbook}/tests/test_write.hpp (73%) rename source/{serialization => workbook}/tests/test_write_workbook.hpp (84%) diff --git a/include/xlnt/serialization/xml_document.hpp b/include/xlnt/serialization/xml_document.hpp deleted file mode 100644 index 9a950b99..00000000 --- a/include/xlnt/serialization/xml_document.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include -#include -#include - -#include - -namespace xlnt { -namespace detail { -struct xml_document_impl; -} - -class xml_node; -class xml_serializer; - -/// -/// Abstracts an XML document from a particular implementation. -/// -class XLNT_CLASS xml_document -{ -public: - using string_pair = std::pair; - - xml_document(); - xml_document(const xml_document &other); - xml_document(xml_document &&other); - ~xml_document(); - - xml_document &operator=(const xml_document &other); - xml_document &operator=(xml_document &&other); - - void set_encoding(const std::string &encoding); - void add_namespace(const std::string &id, const std::string &uri); - - xml_node add_child(const xml_node &child); - xml_node add_child(const std::string &child_name); - - xml_node get_root(); - const xml_node get_root() const; - - xml_node get_child(const std::string &child_name); - const xml_node get_child(const std::string &child_name) const; - - std::string to_string() const; - xml_document &from_string(const std::string &xml_string); - -private: - friend class xml_serializer; - std::unique_ptr d_; -}; - -} // namespace xlnt diff --git a/include/xlnt/serialization/xml_node.hpp b/include/xlnt/serialization/xml_node.hpp deleted file mode 100644 index ad6aa0cb..00000000 --- a/include/xlnt/serialization/xml_node.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include -#include -#include - -#include - -namespace xlnt { -namespace detail { -struct xml_node_impl; -} - -class xml_document; - -/// -/// Abstracts an XML node from a particular implementation. -/// -class XLNT_CLASS xml_node -{ -public: - using string_pair = std::pair; - - xml_node(); - xml_node(const xml_node &other); - ~xml_node(); - - xml_node &operator=(const xml_node &other); - - std::string get_name() const; - void set_name(const std::string &name); - - bool has_text() const; - std::string get_text() const; - void set_text(const std::string &text); - - const std::vector get_children() const; - bool has_child(const std::string &child_name) const; - xml_node get_child(const std::string &child_name); - const xml_node get_child(const std::string &child_name) const; - xml_node add_child(const xml_node &child); - xml_node add_child(const std::string &child_name); - - const std::vector get_attributes() const; - bool has_attribute(const std::string &attribute_name) const; - std::string get_attribute(const std::string &attribute_name) const; - void add_attribute(const std::string &name, const std::string &value); - - std::string to_string() const; - -private: - friend class xml_document; - friend class xml_serializer; - xml_node(const detail::xml_node_impl &d); - std::unique_ptr d_; -}; - -} // namespace xlnt diff --git a/include/xlnt/serialization/xml_serializer.hpp b/include/xlnt/serialization/xml_serializer.hpp deleted file mode 100644 index e70404a9..00000000 --- a/include/xlnt/serialization/xml_serializer.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include - -#include - -namespace xlnt { - -class xml_document; -class xml_node; - -/// -/// Converts XML documents to and from raw strings. -/// -class XLNT_CLASS xml_serializer -{ -public: - static std::string serialize(const xml_document &xml); - static xml_document deserialize(const std::string &xml_string); - - static std::string serialize_node(const xml_node &xml); -}; - -} // namespace xlnt diff --git a/include/xlnt/serialization/encoding.hpp b/include/xlnt/workbook/encoding.hpp similarity index 100% rename from include/xlnt/serialization/encoding.hpp rename to include/xlnt/workbook/encoding.hpp diff --git a/include/xlnt/xlnt.hpp b/include/xlnt/xlnt.hpp index f1525048..53159b5d 100644 --- a/include/xlnt/xlnt.hpp +++ b/include/xlnt/xlnt.hpp @@ -43,9 +43,6 @@ #include #include -// serialization -#include - // styles #include #include @@ -74,6 +71,7 @@ // workbook #include #include +#include #include #include #include diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index 80fc9e0f..eb204550 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/source/serialization/comment_serializer.cpp b/source/detail/comment_serializer.cpp similarity index 94% rename from source/serialization/comment_serializer.cpp rename to source/detail/comment_serializer.cpp index 3fbf9e73..0eed9df7 100644 --- a/source/serialization/comment_serializer.cpp +++ b/source/detail/comment_serializer.cpp @@ -21,12 +21,14 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include +#include namespace xlnt { +namespace detail { comment_serializer::comment_serializer(worksheet sheet) : sheet_(sheet) { } +} // namespace detail } // namespace xlnt diff --git a/include/xlnt/serialization/comment_serializer.hpp b/source/detail/comment_serializer.hpp similarity index 84% rename from include/xlnt/serialization/comment_serializer.hpp rename to source/detail/comment_serializer.hpp index 43e4a672..fcbf6292 100644 --- a/include/xlnt/serialization/comment_serializer.hpp +++ b/source/detail/comment_serializer.hpp @@ -29,9 +29,12 @@ #include #include -namespace xlnt { - +namespace pugi { class xml_document; +} // namespace pugi + +namespace xlnt { +namespace detail { /// /// Manages converting comments to and from XML. @@ -40,14 +43,15 @@ class XLNT_CLASS comment_serializer { comment_serializer(worksheet sheet); - void read_comments(const xml_document &xml); - void read_comments_vml(const xml_document &xml); + void read_comments(const pugi::xml_document &xml); + void read_comments_vml(const pugi::xml_document &xml); - xml_document write_comments() const; - xml_document write_comments_vml() const; + void write_comments(pugi::xml_document &xml) const; + void write_comments_vml(pugi::xml_document &xml) const; private: worksheet sheet_; }; +} // namespace detail } // namespace xlnt diff --git a/source/serialization/excel_serializer.cpp b/source/detail/excel_serializer.cpp similarity index 73% rename from source/serialization/excel_serializer.cpp rename to source/detail/excel_serializer.cpp index 6c7aae88..cba36670 100644 --- a/source/serialization/excel_serializer.cpp +++ b/source/detail/excel_serializer.cpp @@ -23,19 +23,20 @@ // @author: see AUTHORS file #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -46,10 +47,6 @@ #include #include -#include -#include -#include - namespace { std::string::size_type find_string_in_string(const std::string &string, const std::string &substring) @@ -80,8 +77,8 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl } xlnt::manifest_serializer ms(wb.get_manifest()); - xlnt::xml_document manifest_xml; - manifest_xml.from_string(archive.read(xlnt::constants::ArcContentTypes())); + pugi::xml_document manifest_xml; + manifest_xml.load(archive.read(xlnt::constants::ArcContentTypes()).c_str()); ms.read_manifest(manifest_xml); if (ms.determine_document_type() != "excel") @@ -94,16 +91,16 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl if(archive.has_file(xlnt::constants::ArcCore())) { xlnt::workbook_serializer workbook_serializer_(wb); - xlnt::xml_document core_properties_xml; - core_properties_xml.from_string(archive.read(xlnt::constants::ArcCore())); + pugi::xml_document core_properties_xml; + core_properties_xml.load(archive.read(xlnt::constants::ArcCore()).c_str()); workbook_serializer_.read_properties_core(core_properties_xml); } if(archive.has_file(xlnt::constants::ArcApp())) { xlnt::workbook_serializer workbook_serializer_(wb); - xlnt::xml_document app_properties_xml; - app_properties_xml.from_string(archive.read(xlnt::constants::ArcApp())); + pugi::xml_document app_properties_xml; + app_properties_xml.load(archive.read(xlnt::constants::ArcApp()).c_str()); workbook_serializer_.read_properties_app(app_properties_xml); } @@ -122,22 +119,22 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl wb.create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type()); } - xlnt::xml_document xml; - xml.from_string(archive.read(xlnt::constants::ArcWorkbook())); + pugi::xml_document xml; + xml.load(archive.read(xlnt::constants::ArcWorkbook()).c_str()); - auto root_node = xml.get_child("workbook"); + auto root_node = xml.child("workbook"); - auto workbook_pr_node = root_node.get_child("workbookPr"); + auto workbook_pr_node = root_node.child("workbookPr"); wb.get_properties().excel_base_date = - (workbook_pr_node.has_attribute("date1904") && workbook_pr_node.get_attribute("date1904") != "0") + (workbook_pr_node.attribute("date1904") && workbook_pr_node.attribute("date1904").value() != std::string("0")) ? xlnt::calendar::mac_1904 : xlnt::calendar::windows_1900; if(archive.has_file(xlnt::constants::ArcSharedString())) { std::vector shared_strings; - xlnt::xml_document shared_strings_xml; - shared_strings_xml.from_string(archive.read(xlnt::constants::ArcSharedString())); + pugi::xml_document shared_strings_xml; + shared_strings_xml.load(archive.read(xlnt::constants::ArcSharedString()).c_str()); xlnt::shared_strings_serializer::read_shared_strings(shared_strings_xml, shared_strings); for (auto &shared_string : shared_strings) @@ -148,16 +145,16 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl xlnt::detail::stylesheet stylesheet; xlnt::style_serializer style_serializer(stylesheet); - xlnt::xml_document style_xml; - style_xml.from_string(archive.read(xlnt::constants::ArcStyles())); + pugi::xml_document style_xml; + style_xml.load(archive.read(xlnt::constants::ArcStyles()).c_str()); style_serializer.read_stylesheet(style_xml); - auto sheets_node = root_node.get_child("sheets"); + auto sheets_node = root_node.child("sheets"); - for (auto sheet_node : sheets_node.get_children()) + for (auto sheet_node : sheets_node.children()) { - auto rel = wb.get_relationship(sheet_node.get_attribute("r:id")); - auto ws = wb.create_sheet(sheet_node.get_attribute("name"), rel); + auto rel = wb.get_relationship(sheet_node.attribute("r:id").value()); + auto ws = wb.create_sheet(sheet_node.attribute("name").value(), rel); //TODO: this is really bad auto ws_filename = (rel.get_target_uri().substr(0, 3) != "xl/" ? "xl/" : "") + rel.get_target_uri(); @@ -170,8 +167,8 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl } xlnt::worksheet_serializer worksheet_serializer(ws); - xlnt::xml_document worksheet_xml; - worksheet_xml.from_string(archive.read(ws_filename)); + pugi::xml_document worksheet_xml; + worksheet_xml.load(archive.read(ws_filename).c_str()); worksheet_serializer.read_worksheet(worksheet_xml, stylesheet); } @@ -249,31 +246,51 @@ void excel_serializer::write_data(bool /*as_template*/) relationship_serializer_.write_relationships(workbook_.get_root_relationships(), ""); relationship_serializer_.write_relationships(workbook_.get_relationships(), constants::ArcWorkbook()); - xml_document properties_app_xml; + pugi::xml_document properties_app_xml; workbook_serializer workbook_serializer_(workbook_); - archive_.writestr(constants::ArcApp(), xml_serializer::serialize(workbook_serializer_.write_properties_app())); - archive_.writestr(constants::ArcCore(), xml_serializer::serialize(workbook_serializer_.write_properties_core())); + workbook_serializer_.write_properties_app(properties_app_xml); + std::ostringstream ss; + properties_app_xml.save(ss); + archive_.writestr(constants::ArcApp(), ss.str()); + pugi::xml_document properties_core_xml; + workbook_serializer_.write_properties_core(properties_core_xml); + properties_core_xml.save(ss); + archive_.writestr(constants::ArcCore(), ss.str()); + + pugi::xml_document theme_xml; theme_serializer theme_serializer_; - archive_.writestr(constants::ArcTheme(), theme_serializer_.write_theme(workbook_.get_loaded_theme()).to_string()); + theme_serializer_.write_theme(workbook_.get_loaded_theme(), theme_xml); + theme_xml.save(ss); + archive_.writestr(constants::ArcTheme(), ss.str()); if (!workbook_.get_shared_strings().empty()) { const auto &strings = workbook_.get_shared_strings(); - auto shared_strings_xml = xlnt::shared_strings_serializer::write_shared_strings(strings); - - archive_.writestr(constants::ArcSharedString(), xml_serializer::serialize(shared_strings_xml)); + pugi::xml_document shared_strings_xml; + shared_strings_serializer strings_serializer; + strings_serializer.write_shared_strings(strings, shared_strings_xml); + shared_strings_xml.save(ss); + + archive_.writestr(constants::ArcSharedString(), ss.str()); } - archive_.writestr(constants::ArcWorkbook(), xml_serializer::serialize(workbook_serializer_.write_workbook())); + pugi::xml_document workbook_xml; + workbook_serializer_.write_workbook(workbook_xml); + workbook_xml.save(ss); + archive_.writestr(constants::ArcWorkbook(), ss.str()); style_serializer style_serializer(workbook_.d_->stylesheet_); - xlnt::xml_document style_xml; + pugi::xml_document style_xml; style_serializer.write_stylesheet(style_xml); - archive_.writestr(constants::ArcStyles(), style_xml.to_string()); + style_xml.save(ss); + archive_.writestr(constants::ArcStyles(), ss.str()); manifest_serializer manifest_serializer_(workbook_.get_manifest()); - archive_.writestr(constants::ArcContentTypes(), manifest_serializer_.write_manifest().to_string()); + pugi::xml_document manifest_xml; + manifest_serializer_.write_manifest(manifest_xml); + manifest_xml.save(ss); + archive_.writestr(constants::ArcContentTypes(), ss.str()); write_worksheets(); @@ -297,7 +314,12 @@ void excel_serializer::write_worksheets() { worksheet_serializer serializer_(ws); std::string ws_filename = (relationship.get_target_uri().substr(0, 3) != "xl/" ? "xl/" : "") + relationship.get_target_uri(); - archive_.writestr(ws_filename, serializer_.write_worksheet().to_string()); + std::ostringstream ss; + pugi::xml_document worksheet_xml; + serializer_.write_worksheet(worksheet_xml); + worksheet_xml.save(ss); + archive_.writestr(ws_filename, ss.str()); + break; } } diff --git a/include/xlnt/serialization/excel_serializer.hpp b/source/detail/excel_serializer.hpp similarity index 100% rename from include/xlnt/serialization/excel_serializer.hpp rename to source/detail/excel_serializer.hpp diff --git a/source/serialization/manifest_serializer.cpp b/source/detail/manifest_serializer.cpp similarity index 64% rename from source/serialization/manifest_serializer.cpp rename to source/detail/manifest_serializer.cpp index 15697bfb..e3155461 100644 --- a/source/serialization/manifest_serializer.cpp +++ b/source/detail/manifest_serializer.cpp @@ -21,12 +21,12 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include -#include -#include -#include + +#include #include +#include +#include namespace xlnt { @@ -34,45 +34,41 @@ manifest_serializer::manifest_serializer(manifest &m) : manifest_(m) { } -void manifest_serializer::read_manifest(const xml_document &xml) +void manifest_serializer::read_manifest(const pugi::xml_document &xml) { - const auto root_node = xml.get_child("Types"); + const auto root_node = xml.child("Types"); - for (const auto child : root_node.get_children()) + for (const auto child : root_node.children()) { - if (child.get_name() == "Default") + if (child.name() == std::string("Default")) { - manifest_.add_default_type(child.get_attribute("Extension"), child.get_attribute("ContentType")); + manifest_.add_default_type(child.attribute("Extension").value(), child.attribute("ContentType").value()); } - else if (child.get_name() == "Override") + else if (child.name() == std::string("Override")) { - manifest_.add_override_type(child.get_attribute("PartName"), child.get_attribute("ContentType")); + manifest_.add_override_type(child.attribute("PartName").value(), child.attribute("ContentType").value()); } } } -xml_document manifest_serializer::write_manifest() const +void manifest_serializer::write_manifest(pugi::xml_document &xml) const { - xml_document xml; - - auto root_node = xml.add_child("Types"); - xml.add_namespace("", constants::Namespace("content-types")); + auto root_node = xml.append_child("Types"); + root_node.append_attribute("xmlns").set_value(constants::Namespace("content-types").c_str()); for (const auto default_type : manifest_.get_default_types()) { - auto type_node = root_node.add_child("Default"); - type_node.add_attribute("Extension", default_type.get_extension()); - type_node.add_attribute("ContentType", default_type.get_content_type()); + auto type_node = root_node.append_child("Default"); + type_node.append_attribute("Extension").set_value(default_type.get_extension().c_str()); + type_node.append_attribute("ContentType").set_value(default_type.get_content_type().c_str()); } for (const auto override_type : manifest_.get_override_types()) { - auto type_node = root_node.add_child("Override"); - type_node.add_attribute("PartName", override_type.get_part_name()); - type_node.add_attribute("ContentType", override_type.get_content_type()); + auto type_node = root_node.append_child("Override"); + type_node.append_attribute("PartName").set_value(override_type.get_part_name().c_str()); + type_node.append_attribute("ContentType").set_value(override_type.get_content_type().c_str()); } - - return xml; } std::string manifest_serializer::determine_document_type() const diff --git a/include/xlnt/serialization/manifest_serializer.hpp b/source/detail/manifest_serializer.hpp similarity index 91% rename from include/xlnt/serialization/manifest_serializer.hpp rename to source/detail/manifest_serializer.hpp index be280853..ec4323fd 100644 --- a/include/xlnt/serialization/manifest_serializer.hpp +++ b/source/detail/manifest_serializer.hpp @@ -27,10 +27,13 @@ #include +namespace pugi { +class xml_document; +} // namespace pugi + namespace xlnt { class manifest; -class xml_document; /// /// Manages converting a manifest to and from XML. @@ -40,8 +43,8 @@ class XLNT_CLASS manifest_serializer public: manifest_serializer(manifest &m); - void read_manifest(const xml_document &xml); - xml_document write_manifest() const; + void read_manifest(const pugi::xml_document &xml); + void write_manifest(pugi::xml_document &xml) const; std::string determine_document_type() const; diff --git a/source/serialization/relationship_serializer.cpp b/source/detail/relationship_serializer.cpp similarity index 65% rename from source/serialization/relationship_serializer.cpp rename to source/detail/relationship_serializer.cpp index 53d15862..a2dc0a2c 100644 --- a/source/serialization/relationship_serializer.cpp +++ b/source/detail/relationship_serializer.cpp @@ -21,14 +21,14 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include +#include +#include + +#include +#include #include #include -#include -#include - -#include "detail/constants.hpp" namespace { @@ -57,23 +57,18 @@ relationship_serializer::relationship_serializer(zip_file &archive) : archive_(a std::vector relationship_serializer::read_relationships(const std::string &target) { - xml_document xml; - xml.from_string(archive_.read(make_rels_name(target))); + pugi::xml_document xml; + xml.load(archive_.read(make_rels_name(target)).c_str()); - auto root_node = xml.get_child("Relationships"); + auto root_node = xml.child("Relationships"); std::vector relationships; - for (auto relationship_node : root_node.get_children()) + for (auto relationship_node : root_node.children("Relationship")) { - if (relationship_node.get_name() != "Relationship") - { - continue; - } - - std::string id = relationship_node.get_attribute("Id"); - std::string type = relationship_node.get_attribute("Type"); - std::string rel_target = relationship_node.get_attribute("Target"); + std::string id = relationship_node.attribute("Id").value(); + std::string type = relationship_node.attribute("Type").value(); + std::string rel_target = relationship_node.attribute("Target").value(); relationships.push_back(xlnt::relationship(type, id, rel_target)); } @@ -84,27 +79,29 @@ std::vector relationship_serializer::read_relationships(const std: bool relationship_serializer::write_relationships(const std::vector &relationships, const std::string &target) { - xml_document xml; + pugi::xml_document xml; - auto root_node = xml.add_child("Relationships"); + auto root_node = xml.append_child("Relationships"); - xml.add_namespace("", constants::Namespace("relationships")); + root_node.append_attribute("xmlns").set_value(constants::Namespace("relationships").c_str()); for (const auto &relationship : relationships) { - auto relationship_node = root_node.add_child("Relationship"); + auto relationship_node = root_node.append_child("Relationship"); - relationship_node.add_attribute("Id", relationship.get_id()); - relationship_node.add_attribute("Type", relationship.get_type_string()); - relationship_node.add_attribute("Target", relationship.get_target_uri()); + relationship_node.append_attribute("Id").set_value(relationship.get_id().c_str()); + relationship_node.append_attribute("Type").set_value(relationship.get_type_string().c_str()); + relationship_node.append_attribute("Target").set_value(relationship.get_target_uri().c_str()); if (relationship.get_target_mode() == target_mode::external) { - relationship_node.add_attribute("TargetMode", "External"); + relationship_node.append_attribute("TargetMode").set_value("External"); } } - archive_.writestr(make_rels_name(target), xml.to_string()); + std::ostringstream ss; + xml.save(ss); + archive_.writestr(make_rels_name(target), ss.str()); return true; } diff --git a/include/xlnt/serialization/relationship_serializer.hpp b/source/detail/relationship_serializer.hpp similarity index 100% rename from include/xlnt/serialization/relationship_serializer.hpp rename to source/detail/relationship_serializer.hpp diff --git a/source/serialization/shared_strings_serializer.cpp b/source/detail/shared_strings_serializer.cpp similarity index 54% rename from source/serialization/shared_strings_serializer.cpp rename to source/detail/shared_strings_serializer.cpp index 8bc3a612..61fc6b6a 100644 --- a/source/serialization/shared_strings_serializer.cpp +++ b/source/detail/shared_strings_serializer.cpp @@ -22,10 +22,10 @@ // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include +#include + +#include #include -#include -#include namespace { @@ -42,134 +42,125 @@ std::size_t string_to_size_t(const std::string &s) namespace xlnt { -xml_document shared_strings_serializer::write_shared_strings(const std::vector &strings) +void shared_strings_serializer::write_shared_strings(const std::vector &strings, pugi::xml_document &xml) { - xml_document xml; + auto root_node = xml.append_child("sst"); - auto root_node = xml.add_child("sst"); + root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - xml.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - - root_node.add_attribute("count", std::to_string(strings.size())); - root_node.add_attribute("uniqueCount", std::to_string(strings.size())); + root_node.append_attribute("count").set_value(std::to_string(strings.size()).c_str()); + root_node.append_attribute("uniqueCount").set_value(std::to_string(strings.size()).c_str()); for (const auto &string : strings) { if (string.get_runs().size() == 1 && !string.get_runs().at(0).has_formatting()) { - root_node.add_child("si").add_child("t").set_text(string.get_plain_string()); + root_node.append_child("si").append_child("t").text().set(string.get_plain_string().c_str()); } else { - auto string_item_node = root_node.add_child("si"); + auto string_item_node = root_node.append_child("si"); for (const auto &run : string.get_runs()) { - auto rich_text_run_node = string_item_node.add_child("r"); + auto rich_text_run_node = string_item_node.append_child("r"); if (run.has_formatting()) { - auto run_properties_node = rich_text_run_node.add_child("rPr"); + auto run_properties_node = rich_text_run_node.append_child("rPr"); if (run.has_size()) { - run_properties_node.add_child("sz").add_attribute("val", std::to_string(run.get_size())); + run_properties_node.append_child("sz").append_attribute("val").set_value(std::to_string(run.get_size()).c_str()); } if (run.has_color()) { - run_properties_node.add_child("color").add_attribute("rgb", run.get_color()); + run_properties_node.append_child("color").append_attribute("rgb").set_value(run.get_color().c_str()); } if (run.has_font()) { - run_properties_node.add_child("rFont").add_attribute("val", run.get_font()); + run_properties_node.append_child("rFont").append_attribute("val").set_value(run.get_font().c_str()); } if (run.has_family()) { - run_properties_node.add_child("family").add_attribute("val", std::to_string(run.get_family())); + run_properties_node.append_child("family").append_attribute("val").set_value(std::to_string(run.get_family()).c_str()); } if (run.has_scheme()) { - run_properties_node.add_child("scheme").add_attribute("val", run.get_scheme()); + run_properties_node.append_child("scheme").append_attribute("val").set_value(run.get_scheme().c_str()); } } - auto text_node = rich_text_run_node.add_child("t"); - text_node.set_text(run.get_string()); + auto text_node = rich_text_run_node.append_child("t"); + text_node.text().set(run.get_string().c_str()); } } } - - return xml; } -bool shared_strings_serializer::read_shared_strings(const xml_document &xml, std::vector &strings) +bool shared_strings_serializer::read_shared_strings(const pugi::xml_document &xml, std::vector &strings) { strings.clear(); - auto root_node = xml.get_child("sst"); + auto root_node = xml.child("sst"); std::size_t unique_count = 0; - if (root_node.has_attribute("uniqueCount")) + if (root_node.attribute("uniqueCount")) { - unique_count = string_to_size_t(root_node.get_attribute("uniqueCount")); + unique_count = string_to_size_t(root_node.attribute("uniqueCount").value()); } - for (const auto &string_item_node : root_node.get_children()) + for (const auto string_item_node : root_node.children("si")) { - if (string_item_node.get_name() != "si") - { - continue; - } - - if (string_item_node.has_child("t")) + if (string_item_node.child("t")) { text t; - t.set_plain_string(string_item_node.get_child("t").get_text()); + t.set_plain_string(string_item_node.child("t").text().get()); strings.push_back(t); } - else if (string_item_node.has_child("r")) // possible multiple text entities. + else if (string_item_node.child("r")) // possible multiple text entities. { text t; - for (const auto& rich_text_run_node : string_item_node.get_children()) + for (const auto& rich_text_run_node : string_item_node.children("r")) { - if (rich_text_run_node.get_name() == "r" && rich_text_run_node.has_child("t")) + if (rich_text_run_node.child("t")) { text_run run; - run.set_string(rich_text_run_node.get_child("t").get_text()); + run.set_string(rich_text_run_node.child("t").text().get()); - if (rich_text_run_node.has_child("rPr")) + if (rich_text_run_node.child("rPr")) { - auto run_properties_node = rich_text_run_node.get_child("rPr"); + auto run_properties_node = rich_text_run_node.child("rPr"); - if (run_properties_node.has_child("sz")) + if (run_properties_node.child("sz")) { - run.set_size(string_to_size_t(run_properties_node.get_child("sz").get_attribute("val"))); + run.set_size(string_to_size_t(run_properties_node.child("sz").attribute("val").value())); } - if (run_properties_node.has_child("rFont")) + if (run_properties_node.child("rFont")) { - run.set_font(run_properties_node.get_child("rFont").get_attribute("val")); + run.set_font(run_properties_node.child("rFont").attribute("val").value()); } - if (run_properties_node.has_child("color")) + if (run_properties_node.child("color")) { - run.set_color(run_properties_node.get_child("color").get_attribute("rgb")); + run.set_color(run_properties_node.child("color").attribute("rgb").value()); } - if (run_properties_node.has_child("family")) + if (run_properties_node.child("family")) { - run.set_family(string_to_size_t(run_properties_node.get_child("family").get_attribute("val"))); + run.set_family(string_to_size_t(run_properties_node.child("family").attribute("val").value())); } - if (run_properties_node.has_child("scheme")) + if (run_properties_node.child("scheme")) { - run.set_scheme(run_properties_node.get_child("scheme").get_attribute("val")); + run.set_scheme(run_properties_node.child("scheme").attribute("val").value()); } } diff --git a/include/xlnt/serialization/shared_strings_serializer.hpp b/source/detail/shared_strings_serializer.hpp similarity index 86% rename from include/xlnt/serialization/shared_strings_serializer.hpp rename to source/detail/shared_strings_serializer.hpp index 8ced3b37..3e49b74c 100644 --- a/include/xlnt/serialization/shared_strings_serializer.hpp +++ b/source/detail/shared_strings_serializer.hpp @@ -27,10 +27,13 @@ #include +namespace pugi { +class xml_document; +} // namespace pugi + namespace xlnt { class text; -class xml_document; /// /// Manages converting a set of shared strings to and from XML. @@ -38,8 +41,8 @@ class xml_document; class XLNT_CLASS shared_strings_serializer { public: - static bool read_shared_strings(const xml_document &xml, std::vector &strings); - static xml_document write_shared_strings(const std::vector &strings); + static bool read_shared_strings(const pugi::xml_document &xml, std::vector &strings); + static void write_shared_strings(const std::vector &strings, pugi::xml_document &xml); }; } // namespace xlnt diff --git a/source/serialization/style_serializer.cpp b/source/detail/style_serializer.cpp similarity index 58% rename from source/serialization/style_serializer.cpp rename to source/detail/style_serializer.cpp index af1d164d..003b4f72 100644 --- a/source/serialization/style_serializer.cpp +++ b/source/detail/style_serializer.cpp @@ -24,15 +24,14 @@ #include #include // for std::tolower +#include #include #include // for std::move -#include -#include +#include #include +#include #include -#include -#include #include #include #include @@ -395,54 +394,49 @@ std::string horizontal_alignment_to_string(xlnt::horizontal_alignment horizontal // Reading -xlnt::protection read_protection(const xlnt::xml_node &protection_node) +xlnt::protection read_protection(const pugi::xml_node protection_node) { xlnt::protection prot; - prot.set_locked(protection_type_from_string(protection_node.get_attribute("locked"))); - prot.set_hidden(protection_type_from_string(protection_node.get_attribute("hidden"))); + prot.set_locked(protection_type_from_string(protection_node.attribute("locked").value())); + prot.set_hidden(protection_type_from_string(protection_node.attribute("hidden").value())); return std::move(prot); } -xlnt::alignment read_alignment(const xlnt::xml_node &alignment_node) +xlnt::alignment read_alignment(const pugi::xml_node alignment_node) { xlnt::alignment align; - align.set_wrap_text(is_true(alignment_node.get_attribute("wrapText"))); - align.set_shrink_to_fit(is_true(alignment_node.get_attribute("shrinkToFit"))); + align.set_wrap_text(is_true(alignment_node.attribute("wrapText").value())); + align.set_shrink_to_fit(is_true(alignment_node.attribute("shrinkToFit").value())); - bool has_vertical = alignment_node.has_attribute("vertical"); + bool has_vertical = alignment_node.attribute("vertical"); if (has_vertical) { - std::string vertical = alignment_node.get_attribute("vertical"); + std::string vertical = alignment_node.attribute("vertical").value(); align.set_vertical(vertical_alignment_from_string(vertical)); } - bool has_horizontal = alignment_node.has_attribute("horizontal"); + bool has_horizontal = alignment_node.attribute("horizontal"); if (has_horizontal) { - std::string horizontal = alignment_node.get_attribute("horizontal"); + std::string horizontal = alignment_node.attribute("horizontal").value(); align.set_horizontal(horizontal_alignment_from_string(horizontal)); } return align; } -void read_number_formats(const xlnt::xml_node &number_formats_node, std::vector &number_formats) +void read_number_formats(const pugi::xml_node number_formats_node, std::vector &number_formats) { number_formats.clear(); - for (auto num_fmt_node : number_formats_node.get_children()) + for (auto num_fmt_node : number_formats_node.children("numFmt")) { - if (num_fmt_node.get_name() != "numFmt") - { - continue; - } - - auto format_string = num_fmt_node.get_attribute("formatCode"); + std::string format_string(num_fmt_node.attribute("formatCode").value()); if (format_string == "GENERAL") { @@ -452,61 +446,61 @@ void read_number_formats(const xlnt::xml_node &number_formats_node, std::vector< xlnt::number_format nf; nf.set_format_string(format_string); - nf.set_id(string_to_size_t(num_fmt_node.get_attribute("numFmtId"))); + nf.set_id(string_to_size_t(num_fmt_node.attribute("numFmtId").value())); number_formats.push_back(nf); } } -xlnt::color read_color(const xlnt::xml_node &color_node) +xlnt::color read_color(const pugi::xml_node &color_node) { - if (color_node.has_attribute("rgb")) + if (color_node.attribute("rgb")) { - return xlnt::color(xlnt::color::type::rgb, color_node.get_attribute("rgb")); + return xlnt::color(xlnt::color::type::rgb, color_node.attribute("rgb").value()); } - else if (color_node.has_attribute("theme")) + else if (color_node.attribute("theme")) { - return xlnt::color(xlnt::color::type::theme, string_to_size_t(color_node.get_attribute("theme"))); + return xlnt::color(xlnt::color::type::theme, string_to_size_t(color_node.attribute("theme").value())); } - else if (color_node.has_attribute("indexed")) + else if (color_node.attribute("indexed")) { - return xlnt::color(xlnt::color::type::indexed, string_to_size_t(color_node.get_attribute("indexed"))); + return xlnt::color(xlnt::color::type::indexed, string_to_size_t(color_node.attribute("indexed").value())); } - else if (color_node.has_attribute("auto")) + else if (color_node.attribute("auto")) { - return xlnt::color(xlnt::color::type::auto_, string_to_size_t(color_node.get_attribute("auto"))); + return xlnt::color(xlnt::color::type::auto_, string_to_size_t(color_node.attribute("auto").value())); } throw std::runtime_error("bad color"); } -xlnt::font read_font(const xlnt::xml_node &font_node) +xlnt::font read_font(const pugi::xml_node font_node) { xlnt::font new_font; - new_font.set_size(string_to_size_t(font_node.get_child("sz").get_attribute("val"))); - new_font.set_name(font_node.get_child("name").get_attribute("val")); + new_font.set_size(string_to_size_t(font_node.child("sz").attribute("val").value())); + new_font.set_name(font_node.child("name").attribute("val").value()); - if (font_node.has_child("color")) + if (font_node.child("color")) { - new_font.set_color(read_color(font_node.get_child("color"))); + new_font.set_color(read_color(font_node.child("color"))); } - if (font_node.has_child("family")) + if (font_node.child("family")) { - new_font.set_family(string_to_size_t(font_node.get_child("family").get_attribute("val"))); + new_font.set_family(string_to_size_t(font_node.child("family").attribute("val").value())); } - if (font_node.has_child("scheme")) + if (font_node.child("scheme")) { - new_font.set_scheme(font_node.get_child("scheme").get_attribute("val")); + new_font.set_scheme(font_node.child("scheme").attribute("val").value()); } - if (font_node.has_child("b")) + if (font_node.child("b")) { - if(font_node.get_child("b").has_attribute("val")) + if(font_node.child("b").attribute("val")) { - new_font.set_bold(is_true(font_node.get_child("b").get_attribute("val"))); + new_font.set_bold(is_true(font_node.child("b").attribute("val").value())); } else { @@ -514,11 +508,11 @@ xlnt::font read_font(const xlnt::xml_node &font_node) } } - if (font_node.has_child("strike")) + if (font_node.child("strike")) { - if(font_node.get_child("strike").has_attribute("val")) + if(font_node.child("strike").attribute("val")) { - new_font.set_strikethrough(is_true(font_node.get_child("strike").get_attribute("val"))); + new_font.set_strikethrough(is_true(font_node.child("strike").attribute("val").value())); } else { @@ -526,11 +520,11 @@ xlnt::font read_font(const xlnt::xml_node &font_node) } } - if (font_node.has_child("i")) + if (font_node.child("i")) { - if(font_node.get_child("i").has_attribute("val")) + if(font_node.child("i").attribute("val")) { - new_font.set_italic(is_true(font_node.get_child("i").get_attribute("val"))); + new_font.set_italic(is_true(font_node.child("i").attribute("val").value())); } else { @@ -538,11 +532,11 @@ xlnt::font read_font(const xlnt::xml_node &font_node) } } - if (font_node.has_child("u")) + if (font_node.child("u")) { - if (font_node.get_child("u").has_attribute("val")) + if (font_node.child("u").attribute("val")) { - std::string underline_string = font_node.get_child("u").get_attribute("val"); + std::string underline_string = font_node.child("u").attribute("val").value(); new_font.set_underline(underline_style_from_string(underline_string)); } else @@ -554,57 +548,57 @@ xlnt::font read_font(const xlnt::xml_node &font_node) return new_font; } -void read_fonts(const xlnt::xml_node &fonts_node, std::vector &fonts) +void read_fonts(const pugi::xml_node &fonts_node, std::vector &fonts) { fonts.clear(); - for (auto font_node : fonts_node.get_children()) + for (auto font_node : fonts_node.children()) { fonts.push_back(read_font(font_node)); } } -void read_indexed_colors(const xlnt::xml_node &indexed_colors_node, std::vector &colors) +void read_indexed_colors(const pugi::xml_node &indexed_colors_node, std::vector &colors) { - for (auto color_node : indexed_colors_node.get_children()) + for (auto color_node : indexed_colors_node.children()) { colors.push_back(read_color(color_node)); } } -void read_colors(const xlnt::xml_node &colors_node, std::vector &colors) +void read_colors(const pugi::xml_node &colors_node, std::vector &colors) { colors.clear(); - if (colors_node.has_child("indexedColors")) + if (colors_node.child("indexedColors")) { - read_indexed_colors(colors_node.get_child("indexedColors"), colors); + read_indexed_colors(colors_node.child("indexedColors"), colors); } } -xlnt::fill read_fill(const xlnt::xml_node &fill_node) +xlnt::fill read_fill(const pugi::xml_node &fill_node) { xlnt::fill new_fill; - if (fill_node.has_child("patternFill")) + if (fill_node.child("patternFill")) { new_fill.set_type(xlnt::fill::type::pattern); - auto pattern_fill_node = fill_node.get_child("patternFill"); - auto pattern_fill_type_string = pattern_fill_node.get_attribute("patternType"); + auto pattern_fill_node = fill_node.child("patternFill"); + std::string pattern_fill_type_string = pattern_fill_node.attribute("patternType").value(); if (!pattern_fill_type_string.empty()) { new_fill.set_pattern_type(pattern_fill_type_from_string(pattern_fill_type_string)); - if (pattern_fill_node.has_child("bgColor")) + if (pattern_fill_node.child("bgColor")) { - new_fill.get_background_color() = read_color(pattern_fill_node.get_child("bgColor")); + new_fill.get_background_color() = read_color(pattern_fill_node.child("bgColor")); } - if (pattern_fill_node.has_child("fgColor")) + if (pattern_fill_node.child("fgColor")) { - new_fill.get_foreground_color() = read_color(pattern_fill_node.get_child("fgColor")); + new_fill.get_foreground_color() = read_color(pattern_fill_node.child("fgColor")); } } } @@ -612,125 +606,125 @@ xlnt::fill read_fill(const xlnt::xml_node &fill_node) return new_fill; } -void read_fills(const xlnt::xml_node &fills_node, std::vector &fills) +void read_fills(const pugi::xml_node &fills_node, std::vector &fills) { fills.clear(); - for (auto fill_node : fills_node.get_children()) + for (auto fill_node : fills_node.children()) { fills.emplace_back(); fills.back() = read_fill(fill_node); } } -xlnt::side read_side(const xlnt::xml_node &side_node) +xlnt::side read_side(const pugi::xml_node &side_node) { xlnt::side new_side; - if (side_node.has_attribute("style")) + if (side_node.attribute("style")) { - new_side.get_border_style() = border_style_from_string(side_node.get_attribute("style")); + new_side.get_border_style() = border_style_from_string(side_node.attribute("style").value()); } - if (side_node.has_child("color")) + if (side_node.child("color")) { - new_side.get_color() = read_color(side_node.get_child("color")); + new_side.get_color() = read_color(side_node.child("color")); } return new_side; } -xlnt::border read_border(const xlnt::xml_node &border_node) +xlnt::border read_border(const pugi::xml_node &border_node) { xlnt::border new_border; - if (border_node.has_child("start")) + if (border_node.child("start")) { - new_border.get_start() = read_side(border_node.get_child("start")); + new_border.get_start() = read_side(border_node.child("start")); } - if (border_node.has_child("end")) + if (border_node.child("end")) { - new_border.get_end() = read_side(border_node.get_child("end")); + new_border.get_end() = read_side(border_node.child("end")); } - if (border_node.has_child("left")) + if (border_node.child("left")) { - new_border.get_left() = read_side(border_node.get_child("left")); + new_border.get_left() = read_side(border_node.child("left")); } - if (border_node.has_child("right")) + if (border_node.child("right")) { - new_border.get_right() = read_side(border_node.get_child("right")); + new_border.get_right() = read_side(border_node.child("right")); } - if (border_node.has_child("top")) + if (border_node.child("top")) { - new_border.get_top() = read_side(border_node.get_child("top")); + new_border.get_top() = read_side(border_node.child("top")); } - if (border_node.has_child("bottom")) + if (border_node.child("bottom")) { - new_border.get_bottom() = read_side(border_node.get_child("bottom")); + new_border.get_bottom() = read_side(border_node.child("bottom")); } - if (border_node.has_child("diagonal")) + if (border_node.child("diagonal")) { - new_border.get_diagonal() = read_side(border_node.get_child("diagonal")); + new_border.get_diagonal() = read_side(border_node.child("diagonal")); } - if (border_node.has_child("vertical")) + if (border_node.child("vertical")) { - new_border.get_vertical() = read_side(border_node.get_child("vertical")); + new_border.get_vertical() = read_side(border_node.child("vertical")); } - if (border_node.has_child("horizontal")) + if (border_node.child("horizontal")) { - new_border.get_horizontal() = read_side(border_node.get_child("horizontal")); + new_border.get_horizontal() = read_side(border_node.child("horizontal")); } return new_border; } -void read_borders(const xlnt::xml_node &borders_node, std::vector &borders) +void read_borders(const pugi::xml_node &borders_node, std::vector &borders) { borders.clear(); - for (auto border_node : borders_node.get_children()) + for (auto border_node : borders_node.children()) { borders.push_back(read_border(border_node)); } } -bool read_base_format(const xlnt::xml_node &format_node, const xlnt::detail::stylesheet &stylesheet, xlnt::base_format &f) +bool read_base_format(const pugi::xml_node &format_node, const xlnt::detail::stylesheet &stylesheet, xlnt::base_format &f) { // Alignment - f.alignment_applied(format_node.has_child("alignment") || is_true(format_node.get_attribute("applyAlignment"))); + f.alignment_applied(format_node.child("alignment") || is_true(format_node.attribute("applyAlignment").value())); if (f.alignment_applied()) { - auto inline_alignment = read_alignment(format_node.get_child("alignment")); + auto inline_alignment = read_alignment(format_node.child("alignment")); f.set_alignment(inline_alignment); } // Border - auto border_index = format_node.has_attribute("borderId") ? string_to_size_t(format_node.get_attribute("borderId")) : 0; + auto border_index = format_node.attribute("borderId") ? string_to_size_t(format_node.attribute("borderId").value()) : 0; f.set_border(stylesheet.borders.at(border_index)); - f.border_applied(is_true(format_node.get_attribute("applyBorder"))); + f.border_applied(is_true(format_node.attribute("applyBorder").value())); // Fill - auto fill_index = format_node.has_attribute("fillId") ? string_to_size_t(format_node.get_attribute("fillId")) : 0; + auto fill_index = format_node.attribute("fillId") ? string_to_size_t(format_node.attribute("fillId").value()) : 0; f.set_fill(stylesheet.fills.at(fill_index)); - f.fill_applied(is_true(format_node.get_attribute("applyFill"))); + f.fill_applied(is_true(format_node.attribute("applyFill").value())); // Font - auto font_index = format_node.has_attribute("fontId") ? string_to_size_t(format_node.get_attribute("fontId")) : 0; + auto font_index = format_node.attribute("fontId") ? string_to_size_t(format_node.attribute("fontId").value()) : 0; f.set_font(stylesheet.fonts.at(font_index)); - f.font_applied(is_true(format_node.get_attribute("applyFont"))); + f.font_applied(is_true(format_node.attribute("applyFont").value())); // Number Format - auto number_format_id = string_to_size_t(format_node.get_attribute("numFmtId")); + auto number_format_id = string_to_size_t(format_node.attribute("numFmtId").value()); bool builtin_format = true; @@ -749,14 +743,14 @@ bool read_base_format(const xlnt::xml_node &format_node, const xlnt::detail::sty f.set_number_format(xlnt::number_format::from_builtin_id(number_format_id)); } - f.number_format_applied(is_true(format_node.get_attribute("applyNumberFormat"))); + f.number_format_applied(is_true(format_node.attribute("applyNumberFormat").value())); // Protection - f.protection_applied(format_node.has_attribute("protection") || is_true(format_node.get_attribute("applyProtection"))); + f.protection_applied(format_node.attribute("protection") || is_true(format_node.attribute("applyProtection").value())); if (f.protection_applied()) { - auto inline_protection = read_protection(format_node.get_child("protection")); + auto inline_protection = read_protection(format_node.child("protection")); f.set_protection(inline_protection); } @@ -764,23 +758,18 @@ bool read_base_format(const xlnt::xml_node &format_node, const xlnt::detail::sty } -void read_formats(const xlnt::xml_node &formats_node, const xlnt::detail::stylesheet &stylesheet, +void read_formats(const pugi::xml_node &formats_node, const xlnt::detail::stylesheet &stylesheet, std::vector &formats, std::vector &format_styles) { - for (auto format_node : formats_node.get_children()) + for (auto format_node : formats_node.children("xf")) { - if (format_node.get_name() != "xf") - { - continue; - } - xlnt::format format; read_base_format(format_node, stylesheet, format); // TODO do all formats have xfId? - if(format_node.has_attribute("xfId")) + if(format_node.attribute("xfId")) { - auto style_index = string_to_size_t(format_node.get_attribute("xfId")); + auto style_index = string_to_size_t(format_node.attribute("xfId").value()); auto style_name = stylesheet.style_name_map.at(style_index); format_styles.push_back(style_name); } @@ -793,30 +782,30 @@ void read_formats(const xlnt::xml_node &formats_node, const xlnt::detail::styles } } -xlnt::style read_style(const xlnt::xml_node &style_node, const xlnt::xml_node &style_format_node, const xlnt::detail::stylesheet &stylesheet) +xlnt::style read_style(const pugi::xml_node &style_node, const pugi::xml_node &style_format_node, const xlnt::detail::stylesheet &stylesheet) { xlnt::style s; read_base_format(style_format_node, stylesheet, s); - s.set_name(style_node.get_attribute("name")); - s.set_hidden(style_node.has_attribute("hidden") && is_true(style_node.get_attribute("hidden"))); - s.set_builtin_id(string_to_size_t(style_node.get_attribute("builtinId"))); + s.set_name(style_node.attribute("name").value()); + s.set_hidden(style_node.attribute("hidden") && is_true(style_node.attribute("hidden").value())); + s.set_builtin_id(string_to_size_t(style_node.attribute("builtinId").value())); return s; } -void read_styles(const xlnt::xml_node &styles_node, const xlnt::xml_node &style_formats_node, const xlnt::detail::stylesheet stylesheet, std::vector &styles, std::unordered_map &style_names) +void read_styles(const pugi::xml_node &styles_node, const pugi::xml_node &style_formats_node, const xlnt::detail::stylesheet stylesheet, std::vector &styles, std::unordered_map &style_names) { std::size_t style_index = 0; - for (auto cell_style_format_node : style_formats_node.get_children()) + for (auto cell_style_format_node : style_formats_node.children()) { bool match = false; - for (auto cell_style_node : styles_node.get_children()) + for (auto cell_style_node : styles_node.children()) { - auto cell_style_format_index = std::stoull(cell_style_node.get_attribute("xfId")); + auto cell_style_format_index = std::stoull(cell_style_node.attribute("xfId").value()); if (cell_style_format_index == style_index) { @@ -832,21 +821,21 @@ void read_styles(const xlnt::xml_node &styles_node, const xlnt::xml_node &style_ } } -bool write_color(const xlnt::color &color, xlnt::xml_node color_node) +bool write_color(const xlnt::color &color, pugi::xml_node color_node) { switch (color.get_type()) { case xlnt::color::type::auto_: - color_node.add_attribute("auto", std::to_string(color.get_auto())); + color_node.append_attribute("auto").set_value(std::to_string(color.get_auto()).c_str()); break; case xlnt::color::type::theme: - color_node.add_attribute("theme", std::to_string(color.get_theme())); + color_node.append_attribute("theme").set_value(std::to_string(color.get_theme()).c_str()); break; case xlnt::color::type::indexed: - color_node.add_attribute("indexed", std::to_string(color.get_index())); + color_node.append_attribute("indexed").set_value(std::to_string(color.get_index()).c_str()); break; case xlnt::color::type::rgb: - color_node.add_attribute("rgb", color.get_rgb_string()); + color_node.append_attribute("rgb").set_value(color.get_rgb_string().c_str()); break; default: throw std::runtime_error("bad type"); @@ -855,116 +844,116 @@ bool write_color(const xlnt::color &color, xlnt::xml_node color_node) return true; } -bool write_fonts(const std::vector &fonts, xlnt::xml_node &fonts_node) +bool write_fonts(const std::vector &fonts, pugi::xml_node &fonts_node) { - fonts_node.add_attribute("count", std::to_string(fonts.size())); + fonts_node.append_attribute("count").set_value(std::to_string(fonts.size()).c_str()); // TODO: what does this do? - // fonts_node.add_attribute("x14ac:knownFonts", "1"); + // fonts_node.append_attribute("x14ac:knownFonts", "1"); for (auto &f : fonts) { - auto font_node = fonts_node.add_child("font"); + auto font_node = fonts_node.append_child("font"); if (f.is_bold()) { - auto bold_node = font_node.add_child("b"); - bold_node.add_attribute("val", "1"); + auto bold_node = font_node.append_child("b"); + bold_node.append_attribute("val").set_value("1"); } if (f.is_italic()) { - auto italic_node = font_node.add_child("i"); - italic_node.add_attribute("val", "1"); + auto italic_node = font_node.append_child("i"); + italic_node.append_attribute("val").set_value("1"); } if (f.is_underline()) { - auto underline_node = font_node.add_child("u"); - underline_node.add_attribute("val", underline_style_to_string(f.get_underline())); + auto underline_node = font_node.append_child("u"); + underline_node.append_attribute("val").set_value(underline_style_to_string(f.get_underline()).c_str()); } if (f.is_strikethrough()) { - auto strike_node = font_node.add_child("strike"); - strike_node.add_attribute("val", "1"); + auto strike_node = font_node.append_child("strike"); + strike_node.append_attribute("val").set_value("1"); } - auto size_node = font_node.add_child("sz"); - size_node.add_attribute("val", std::to_string(f.get_size())); + auto size_node = font_node.append_child("sz"); + size_node.append_attribute("val").set_value(std::to_string(f.get_size()).c_str()); - auto color_node = font_node.add_child("color"); + auto color_node = font_node.append_child("color"); write_color(f.get_color(), color_node); - auto name_node = font_node.add_child("name"); - name_node.add_attribute("val", f.get_name()); + auto name_node = font_node.append_child("name"); + name_node.append_attribute("val").set_value(f.get_name().c_str()); if (f.has_family()) { - auto family_node = font_node.add_child("family"); - family_node.add_attribute("val", std::to_string(f.get_family())); + auto family_node = font_node.append_child("family"); + family_node.append_attribute("val").set_value(std::to_string(f.get_family()).c_str()); } if (f.has_scheme()) { - auto scheme_node = font_node.add_child("scheme"); - scheme_node.add_attribute("val", "minor"); + auto scheme_node = font_node.append_child("scheme"); + scheme_node.append_attribute("val").set_value("minor"); } } return true; } -bool write_fills(const std::vector &fills, xlnt::xml_node &fills_node) +bool write_fills(const std::vector &fills, pugi::xml_node &fills_node) { - fills_node.add_attribute("count", std::to_string(fills.size())); + fills_node.append_attribute("count").set_value(std::to_string(fills.size()).c_str()); for (auto &fill_ : fills) { - auto fill_node = fills_node.add_child("fill"); + auto fill_node = fills_node.append_child("fill"); if (fill_.get_type() == xlnt::fill::type::pattern) { - auto pattern_fill_node = fill_node.add_child("patternFill"); - pattern_fill_node.add_attribute("patternType", pattern_fill_type_to_string(fill_.get_pattern_type())); + auto pattern_fill_node = fill_node.append_child("patternFill"); + pattern_fill_node.append_attribute("patternType").set_value(pattern_fill_type_to_string(fill_.get_pattern_type()).c_str()); if (fill_.get_pattern_type() != xlnt::fill::pattern_type::solid) continue; if (fill_.get_foreground_color()) { - write_color(*fill_.get_foreground_color(), pattern_fill_node.add_child("fgColor")); + write_color(*fill_.get_foreground_color(), pattern_fill_node.append_child("fgColor")); } if (fill_.get_background_color()) { - write_color(*fill_.get_background_color(), pattern_fill_node.add_child("bgColor")); + write_color(*fill_.get_background_color(), pattern_fill_node.append_child("bgColor")); } } else if (fill_.get_type() == xlnt::fill::type::solid) { - auto solid_fill_node = fill_node.add_child("solidFill"); - solid_fill_node.add_child("color"); + auto solid_fill_node = fill_node.append_child("solidFill"); + solid_fill_node.append_child("color"); } else if (fill_.get_type() == xlnt::fill::type::gradient) { - auto gradient_fill_node = fill_node.add_child("gradientFill"); + auto gradient_fill_node = fill_node.append_child("gradientFill"); if (fill_.get_gradient_type() == xlnt::fill::gradient_type::linear) { - gradient_fill_node.add_attribute("degree", std::to_string(fill_.get_rotation())); + gradient_fill_node.append_attribute("degree").set_value(std::to_string(fill_.get_rotation()).c_str()); } else if (fill_.get_gradient_type() == xlnt::fill::gradient_type::path) { - gradient_fill_node.add_attribute("left", std::to_string(fill_.get_gradient_left())); - gradient_fill_node.add_attribute("right", std::to_string(fill_.get_gradient_right())); - gradient_fill_node.add_attribute("top", std::to_string(fill_.get_gradient_top())); - gradient_fill_node.add_attribute("bottom", std::to_string(fill_.get_gradient_bottom())); + gradient_fill_node.append_attribute("left").set_value(std::to_string(fill_.get_gradient_left()).c_str()); + gradient_fill_node.append_attribute("right").set_value(std::to_string(fill_.get_gradient_right()).c_str()); + gradient_fill_node.append_attribute("top").set_value(std::to_string(fill_.get_gradient_top()).c_str()); + gradient_fill_node.append_attribute("bottom").set_value(std::to_string(fill_.get_gradient_bottom()).c_str()); - auto start_node = gradient_fill_node.add_child("stop"); - start_node.add_attribute("position", "0"); + auto start_node = gradient_fill_node.append_child("stop"); + start_node.append_attribute("position").set_value("0"); - auto end_node = gradient_fill_node.add_child("stop"); - end_node.add_attribute("position", "1"); + auto end_node = gradient_fill_node.append_child("stop"); + end_node.append_attribute("position").set_value("1"); } } } @@ -972,13 +961,13 @@ bool write_fills(const std::vector &fills, xlnt::xml_node &fills_nod return true; } -bool write_borders(const std::vector &borders, xlnt::xml_node &borders_node) +bool write_borders(const std::vector &borders, pugi::xml_node &borders_node) { - borders_node.add_attribute("count", std::to_string(borders.size())); + borders_node.append_attribute("count").set_value(std::to_string(borders.size()).c_str()); for (const auto &border_ : borders) { - auto border_node = borders_node.add_child("border"); + auto border_node = borders_node.append_child("border"); std::vector>> sides; @@ -999,17 +988,17 @@ bool write_borders(const std::vector &borders, xlnt::xml_node &bor if (current_side) { - auto side_node = border_node.add_child(current_name); + auto side_node = border_node.append_child(current_name.c_str()); if (current_side->get_border_style()) { auto style_string = border_style_to_string(*current_side->get_border_style()); - side_node.add_attribute("style", style_string); + side_node.append_attribute("style").set_value(style_string.c_str()); } if (current_side->get_color()) { - auto color_node = side_node.add_child("color"); + auto color_node = side_node.append_child("color"); write_color(*current_side->get_color(), color_node); } } @@ -1019,97 +1008,97 @@ bool write_borders(const std::vector &borders, xlnt::xml_node &bor return true; } -bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, xlnt::xml_node xf_node) +bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, pugi::xml_node xf_node) { - xf_node.add_attribute("numFmtId", std::to_string(xf.get_number_format().get_id())); + xf_node.append_attribute("numFmtId").set_value(std::to_string(xf.get_number_format().get_id()).c_str()); auto font_id = std::distance(stylesheet.fonts.begin(), std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), xf.get_font())); - xf_node.add_attribute("fontId", std::to_string(font_id)); + xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str()); auto fill_id = std::distance(stylesheet.fills.begin(), std::find(stylesheet.fills.begin(), stylesheet.fills.end(), xf.get_fill())); - xf_node.add_attribute("fillId", std::to_string(fill_id)); + xf_node.append_attribute("fillId").set_value(std::to_string(fill_id).c_str()); auto border_id = std::distance(stylesheet.borders.begin(), std::find(stylesheet.borders.begin(), stylesheet.borders.end(), xf.get_border())); - xf_node.add_attribute("borderId", std::to_string(border_id)); + xf_node.append_attribute("borderId").set_value(std::to_string(border_id).c_str()); - if(xf.number_format_applied()) xf_node.add_attribute("applyNumberFormat", "1"); - if(xf.fill_applied()) xf_node.add_attribute("applyFill", "1"); - if(xf.font_applied()) xf_node.add_attribute("applyFont", "1"); - if(xf.border_applied()) xf_node.add_attribute("applyBorder", "1"); - if(xf.alignment_applied()) xf_node.add_attribute("applyAlignment", "1"); - if(xf.protection_applied()) xf_node.add_attribute("applyProtection", "1"); + if(xf.number_format_applied()) xf_node.append_attribute("applyNumberFormat").set_value("1"); + if(xf.fill_applied()) xf_node.append_attribute("applyFill").set_value("1"); + if(xf.font_applied()) xf_node.append_attribute("applyFont").set_value("1"); + if(xf.border_applied()) xf_node.append_attribute("applyBorder").set_value("1"); + if(xf.alignment_applied()) xf_node.append_attribute("applyAlignment").set_value("1"); + if(xf.protection_applied()) xf_node.append_attribute("applyProtection").set_value("1"); if (xf.alignment_applied()) { - auto alignment_node = xf_node.add_child("alignment"); + auto alignment_node = xf_node.append_child("alignment"); if (xf.get_alignment().has_vertical()) { - alignment_node.add_attribute("vertical", vertical_alignment_to_string(xf.get_alignment().get_vertical())); + alignment_node.append_attribute("vertical").set_value(vertical_alignment_to_string(xf.get_alignment().get_vertical()).c_str()); } if (xf.get_alignment().has_horizontal()) { - alignment_node.add_attribute("horizontal", horizontal_alignment_to_string(xf.get_alignment().get_horizontal())); + alignment_node.append_attribute("horizontal").set_value(horizontal_alignment_to_string(xf.get_alignment().get_horizontal()).c_str()); } if (xf.get_alignment().get_wrap_text()) { - alignment_node.add_attribute("wrapText", "1"); + alignment_node.append_attribute("wrapText").set_value("1"); } if (xf.get_alignment().get_shrink_to_fit()) { - alignment_node.add_attribute("shrinkToFit", "1"); + alignment_node.append_attribute("shrinkToFit").set_value("1"); } } if (xf.protection_applied()) { - auto protection_node = xf_node.add_child("protection"); + auto protection_node = xf_node.append_child("protection"); - protection_node.add_attribute("locked", protection_type_to_string(xf.get_protection().get_locked())); - protection_node.add_attribute("hidden", protection_type_to_string(xf.get_protection().get_hidden())); + protection_node.append_attribute("locked").set_value(protection_type_to_string(xf.get_protection().get_locked()).c_str()); + protection_node.append_attribute("hidden").set_value(protection_type_to_string(xf.get_protection().get_hidden()).c_str()); } return true; } -bool write_styles(const xlnt::detail::stylesheet &stylesheet, xlnt::xml_node &styles_node, xlnt::xml_node &style_formats_node) +bool write_styles(const xlnt::detail::stylesheet &stylesheet, pugi::xml_node &styles_node, pugi::xml_node &style_formats_node) { - style_formats_node.add_attribute("count", std::to_string(stylesheet.styles.size())); - styles_node.add_attribute("count", std::to_string(stylesheet.styles.size())); + style_formats_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str()); + styles_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str()); std::size_t style_index = 0; for(auto ¤t_style : stylesheet.styles) { - auto xf_node = style_formats_node.add_child("xf"); + auto xf_node = style_formats_node.append_child("xf"); write_base_format(current_style, stylesheet, xf_node); - auto cell_style_node = styles_node.add_child("cellStyle"); + auto cell_style_node = styles_node.append_child("cellStyle"); - cell_style_node.add_attribute("name", current_style.get_name()); - cell_style_node.add_attribute("xfId", std::to_string(style_index++)); - cell_style_node.add_attribute("builtinId", std::to_string(current_style.get_builtin_id())); + cell_style_node.append_attribute("name").set_value(current_style.get_name().c_str()); + cell_style_node.append_attribute("xfId").set_value(std::to_string(style_index++).c_str()); + cell_style_node.append_attribute("builtinId").set_value(std::to_string(current_style.get_builtin_id()).c_str()); if (current_style.get_hidden()) { - cell_style_node.add_attribute("hidden", "1"); + cell_style_node.append_attribute("hidden").set_value("1"); } } return true; } -bool write_formats(const xlnt::detail::stylesheet &stylesheet, xlnt::xml_node &formats_node) +bool write_formats(const xlnt::detail::stylesheet &stylesheet, pugi::xml_node &formats_node) { - formats_node.add_attribute("count", std::to_string(stylesheet.formats.size())); + formats_node.append_attribute("count").set_value(std::to_string(stylesheet.formats.size()).c_str()); auto format_style_iterator = stylesheet.format_styles.begin(); for(auto ¤t_format : stylesheet.formats) { - auto xf_node = formats_node.add_child("xf"); + auto xf_node = formats_node.append_child("xf"); write_base_format(current_format, stylesheet, xf_node); const auto format_style_name = *(format_style_iterator++); @@ -1120,59 +1109,60 @@ bool write_formats(const xlnt::detail::stylesheet &stylesheet, xlnt::xml_node &f [&](const xlnt::style &s) { return s.get_name() == format_style_name; }); auto style_index = std::distance(stylesheet.styles.begin(), style); - xf_node.add_attribute("xfId", std::to_string(style_index)); + xf_node.append_attribute("xfId").set_value(std::to_string(style_index).c_str()); } } return true; } -bool write_dxfs(xlnt::xml_node &dxfs_node) +bool write_dxfs(pugi::xml_node &dxfs_node) { - dxfs_node.add_attribute("count", "0"); + dxfs_node.append_attribute("count").set_value("0"); return true; } -bool write_table_styles(xlnt::xml_node &table_styles_node) +bool write_table_styles(pugi::xml_node &table_styles_node) { - table_styles_node.add_attribute("count", "0"); - table_styles_node.add_attribute("defaultTableStyle", "TableStyleMedium9"); - table_styles_node.add_attribute("defaultPivotStyle", "PivotStyleMedium7"); + table_styles_node.append_attribute("count").set_value("0"); + table_styles_node.append_attribute("defaultTableStyle").set_value("TableStyleMedium9"); + table_styles_node.append_attribute("defaultPivotStyle").set_value("PivotStyleMedium7"); return true; } -bool write_colors(const std::vector &colors, xlnt::xml_node &colors_node) +bool write_colors(const std::vector &colors, pugi::xml_node &colors_node) { - auto indexed_colors_node = colors_node.add_child("indexedColors"); + auto indexed_colors_node = colors_node.append_child("indexedColors"); for (auto &c : colors) { - indexed_colors_node.add_child("rgbColor").add_attribute("rgb", c.get_rgb_string()); + indexed_colors_node.append_child("rgbColor").append_attribute("rgb").set_value(c.get_rgb_string().c_str()); } return true; } -bool write_ext_list(xlnt::xml_node &ext_list_node) +bool write_ext_list(pugi::xml_node &ext_list_node) { - auto ext_node = ext_list_node.add_child("ext"); - ext_node.add_attribute("uri", "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}"); - ext_node.add_attribute("xmlns:x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); - ext_node.add_child("x14:slicerStyles").add_attribute("defaultSlicerStyle", "SlicerStyleLight1"); + auto ext_node = ext_list_node.append_child("ext"); + + ext_node.append_attribute("uri").set_value("{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}"); + ext_node.append_attribute("xmlns:x14").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); + ext_node.append_child("x14:slicerStyles").append_attribute("defaultSlicerStyle").set_value("SlicerStyleLight1"); return true; } -bool write_number_formats(const std::vector &number_formats, xlnt::xml_node &number_formats_node) +bool write_number_formats(const std::vector &number_formats, pugi::xml_node &number_formats_node) { - number_formats_node.add_attribute("count", std::to_string(number_formats.size())); + number_formats_node.append_attribute("count").set_value(std::to_string(number_formats.size()).c_str()); for (const auto &num_fmt : number_formats) { - auto num_fmt_node = number_formats_node.add_child("numFmt"); - num_fmt_node.add_attribute("numFmtId", std::to_string(num_fmt.get_id())); - num_fmt_node.add_attribute("formatCode", num_fmt.get_format_string()); + auto num_fmt_node = number_formats_node.append_child("numFmt"); + num_fmt_node.append_attribute("numFmtId").set_value(std::to_string(num_fmt.get_id()).c_str()); + num_fmt_node.append_attribute("formatCode").set_value(num_fmt.get_format_string().c_str()); } return true; @@ -1186,74 +1176,74 @@ style_serializer::style_serializer(detail::stylesheet &stylesheet) : stylesheet_ { } -bool style_serializer::read_stylesheet(const xml_document &xml) +bool style_serializer::read_stylesheet(const pugi::xml_document &xml) { - auto stylesheet_node = xml.get_child("styleSheet"); + auto stylesheet_node = xml.child("styleSheet"); - read_borders(stylesheet_node.get_child("borders"), stylesheet_.borders); - read_fills(stylesheet_node.get_child("fills"), stylesheet_.fills); - read_fonts(stylesheet_node.get_child("fonts"), stylesheet_.fonts); - read_number_formats(stylesheet_node.get_child("numFmts"), stylesheet_.number_formats); - read_colors(stylesheet_node.get_child("colors"), stylesheet_.colors); - read_styles(stylesheet_node.get_child("cellStyles"), stylesheet_node.get_child("cellStyleXfs"), stylesheet_, stylesheet_.styles, stylesheet_.style_name_map); - read_formats(stylesheet_node.get_child("cellXfs"), stylesheet_, stylesheet_.formats, stylesheet_.format_styles); + read_borders(stylesheet_node.child("borders"), stylesheet_.borders); + read_fills(stylesheet_node.child("fills"), stylesheet_.fills); + read_fonts(stylesheet_node.child("fonts"), stylesheet_.fonts); + read_number_formats(stylesheet_node.child("numFmts"), stylesheet_.number_formats); + read_colors(stylesheet_node.child("colors"), stylesheet_.colors); + read_styles(stylesheet_node.child("cellStyles"), stylesheet_node.child("cellStyleXfs"), stylesheet_, stylesheet_.styles, stylesheet_.style_name_map); + read_formats(stylesheet_node.child("cellXfs"), stylesheet_, stylesheet_.formats, stylesheet_.format_styles); return true; } -bool style_serializer::write_stylesheet(xml_document &doc) +bool style_serializer::write_stylesheet(pugi::xml_document &doc) { - auto root_node = doc.add_child("styleSheet"); - doc.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - doc.add_namespace("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"); - root_node.add_attribute("mc:Ignorable", "x14ac"); - doc.add_namespace("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"); + auto root_node = doc.append_child("styleSheet"); + root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + root_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006"); + root_node.append_attribute("mc:Ignorable").set_value("x14ac"); + root_node.append_attribute("xmlns:x14ac").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"); if (!stylesheet_.number_formats.empty()) { - auto number_formats_node = root_node.add_child("numFmts"); + auto number_formats_node = root_node.append_child("numFmts"); write_number_formats(stylesheet_.number_formats, number_formats_node); } if (!stylesheet_.fonts.empty()) { - auto fonts_node = root_node.add_child("fonts"); + auto fonts_node = root_node.append_child("fonts"); write_fonts(stylesheet_.fonts, fonts_node); } if (!stylesheet_.fills.empty()) { - auto fills_node = root_node.add_child("fills"); + auto fills_node = root_node.append_child("fills"); write_fills(stylesheet_.fills, fills_node); } if (!stylesheet_.borders.empty()) { - auto borders_node = root_node.add_child("borders"); + auto borders_node = root_node.append_child("borders"); write_borders(stylesheet_.borders, borders_node); } - auto cell_style_xfs_node = root_node.add_child("cellStyleXfs"); + auto cell_style_xfs_node = root_node.append_child("cellStyleXfs"); - auto cell_xfs_node = root_node.add_child("cellXfs"); + auto cell_xfs_node = root_node.append_child("cellXfs"); write_formats(stylesheet_, cell_xfs_node); - auto cell_styles_node = root_node.add_child("cellStyles"); + auto cell_styles_node = root_node.append_child("cellStyles"); write_styles(stylesheet_, cell_styles_node, cell_style_xfs_node); - auto dxfs_node = root_node.add_child("dxfs"); + auto dxfs_node = root_node.append_child("dxfs"); write_dxfs(dxfs_node); - auto table_styles_node = root_node.add_child("tableStyles"); + auto table_styles_node = root_node.append_child("tableStyles"); write_table_styles(table_styles_node); if(!stylesheet_.colors.empty()) { - auto colors_node = root_node.add_child("colors"); + auto colors_node = root_node.append_child("colors"); write_colors(stylesheet_.colors, colors_node); } - auto ext_list_node = root_node.add_child("extLst"); + auto ext_list_node = root_node.append_child("extLst"); write_ext_list(ext_list_node); return true; diff --git a/include/xlnt/serialization/style_serializer.hpp b/source/detail/style_serializer.hpp similarity index 94% rename from include/xlnt/serialization/style_serializer.hpp rename to source/detail/style_serializer.hpp index 580b77cf..8202be8a 100644 --- a/include/xlnt/serialization/style_serializer.hpp +++ b/source/detail/style_serializer.hpp @@ -29,6 +29,10 @@ #include +namespace pugi { +class xml_document; +} // namespace pugi + namespace xlnt { class alignment; @@ -44,8 +48,6 @@ class number_format; class protection; class side; class style; -class xml_document; -class xml_node; namespace detail { struct stylesheet; } @@ -63,13 +65,13 @@ public: /// /// Load all styles from xml_document into workbook given in constructor. /// - bool read_stylesheet(const xml_document &xml); + bool read_stylesheet(const pugi::xml_document &xml); /// /// Populate parameter xml with an XML tree representing the styles contained in the workbook /// given in the constructor. /// - bool write_stylesheet(xml_document &xml); + bool write_stylesheet(pugi::xml_document &xml); private: /// diff --git a/source/detail/theme_serializer.cpp b/source/detail/theme_serializer.cpp new file mode 100644 index 00000000..09fec306 --- /dev/null +++ b/source/detail/theme_serializer.cpp @@ -0,0 +1,370 @@ +// Copyright (c) 2014-2016 Thomas Fussell +// Copyright (c) 2010-2015 openpyxl +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#include +#include + +#include +#include + +namespace xlnt { + +// I have no idea what this stuff is. I hope it was worth it. +void theme_serializer::write_theme(const theme &, pugi::xml_document &xml) const +{ + auto theme_node = xml.append_child("a:theme"); + theme_node.append_attribute("xmlns:a").set_value(constants::Namespace("drawingml").c_str()); + theme_node.append_attribute("name").set_value("Office Theme"); + + auto theme_elements_node = theme_node.append_child("a:themeElements"); + auto clr_scheme_node = theme_elements_node.append_child("a:clrScheme"); + clr_scheme_node.append_attribute("name").set_value("Office"); + + struct scheme_element + { + std::string name; + std::string sub_element_name; + std::string val; + }; + + std::vector scheme_elements = { + { "a:dk1", "a:sysClr", "windowText" }, { "a:lt1", "a:sysClr", "window" }, + { "a:dk2", "a:srgbClr", "1F497D" }, { "a:lt2", "a:srgbClr", "EEECE1" }, + { "a:accent1", "a:srgbClr", "4F81BD" }, { "a:accent2", "a:srgbClr", "C0504D" }, + { "a:accent3", "a:srgbClr", "9BBB59" }, { "a:accent4", "a:srgbClr", "8064A2" }, + { "a:accent5", "a:srgbClr", "4BACC6" }, { "a:accent6", "a:srgbClr", "F79646" }, + { "a:hlink", "a:srgbClr", "0000FF" }, { "a:folHlink", "a:srgbClr", "800080" }, + }; + + for (auto element : scheme_elements) + { + auto element_node = clr_scheme_node.append_child(element.name.c_str()); + element_node.append_child(element.sub_element_name.c_str()).append_attribute("val").set_value(element.val.c_str()); + + if (element.name == "a:dk1") + { + element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("000000"); + } + else if (element.name == "a:lt1") + { + element_node.child(element.sub_element_name.c_str()).append_attribute("lastClr").set_value("FFFFFF"); + } + } + + struct font_scheme + { + bool typeface; + std::string script; + std::string major; + std::string minor; + }; + + std::vector font_schemes = { + { true, "a:latin", "Cambria", "Calibri" }, + { true, "a:ea", "", "" }, + { true, "a:cs", "", "" }, + { false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", + "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" }, + { false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", + "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95" }, + { false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93" }, + { false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", + "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" }, + { false, "Arab", "Times New Roman", "Arial" }, + { false, "Hebr", "Times New Roman", "Arial" }, + { false, "Thai", "Tahoma", "Tahoma" }, + { false, "Ethi", "Nyala", "Nyala" }, + { false, "Beng", "Vrinda", "Vrinda" }, + { false, "Gujr", "Shruti", "Shruti" }, + { false, "Khmr", "MoolBoran", "DaunPenh" }, + { false, "Knda", "Tunga", "Tunga" }, + { false, "Guru", "Raavi", "Raavi" }, + { false, "Cans", "Euphemia", "Euphemia" }, + { false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee" }, + { false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti" }, + { false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya" }, + { false, "Thaa", "MV Boli", "MV Boli" }, + { false, "Deva", "Mangal", "Mangal" }, + { false, "Telu", "Gautami", "Gautami" }, + { false, "Taml", "Latha", "Latha" }, + { false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa" }, + { false, "Orya", "Kalinga", "Kalinga" }, + { false, "Mlym", "Kartika", "Kartika" }, + { false, "Laoo", "DokChampa", "DokChampa" }, + { false, "Sinh", "Iskoola Pota", "Iskoola Pota" }, + { false, "Mong", "Mongolian Baiti", "Mongolian Baiti" }, + { false, "Viet", "Times New Roman", "Arial" }, + { false, "Uigh", "Microsoft Uighur", "Microsoft Uighur" } + }; + + auto font_scheme_node = theme_elements_node.append_child("a:fontScheme"); + font_scheme_node.append_attribute("name").set_value("Office"); + + auto major_fonts_node = font_scheme_node.append_child("a:majorFont"); + auto minor_fonts_node = font_scheme_node.append_child("a:minorFont"); + + for (auto scheme : font_schemes) + { + if (scheme.typeface) + { + auto major_font_node = major_fonts_node.append_child(scheme.script.c_str()); + major_font_node.append_attribute("typeface").set_value(scheme.major.c_str()); + + auto minor_font_node = minor_fonts_node.append_child(scheme.script.c_str()); + minor_font_node.append_attribute("typeface").set_value(scheme.minor.c_str()); + } + else + { + auto major_font_node = major_fonts_node.append_child("a:font"); + major_font_node.append_attribute("script").set_value(scheme.script.c_str()); + major_font_node.append_attribute("typeface").set_value(scheme.major.c_str()); + + auto minor_font_node = minor_fonts_node.append_child("a:font"); + minor_font_node.append_attribute("script").set_value(scheme.script.c_str()); + minor_font_node.append_attribute("typeface").set_value(scheme.minor.c_str()); + } + } + + auto format_scheme_node = theme_elements_node.append_child("a:fmtScheme"); + format_scheme_node.append_attribute("name").set_value("Office"); + + auto fill_style_list_node = format_scheme_node.append_child("a:fillStyleLst"); + fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr"); + + auto grad_fill_node = fill_style_list_node.append_child("a:gradFill"); + grad_fill_node.append_attribute("rotWithShape").set_value("1"); + + auto grad_fill_list = grad_fill_node.append_child("a:gsLst"); + auto gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("0"); + auto scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("50000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("300000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("35000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("37000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("300000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("100000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("15000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("350000"); + + auto lin_node = grad_fill_node.append_child("a:lin"); + lin_node.append_attribute("ang").set_value("16200000"); + lin_node.append_attribute("scaled").set_value("1"); + + grad_fill_node = fill_style_list_node.append_child("a:gradFill"); + grad_fill_node.append_attribute("rotWithShape").set_value("1"); + + grad_fill_list = grad_fill_node.append_child("a:gsLst"); + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("0"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("51000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("130000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("80000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("93000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("130000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("100000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("94000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("135000"); + + lin_node = grad_fill_node.append_child("a:lin"); + lin_node.append_attribute("ang").set_value("16200000"); + lin_node.append_attribute("scaled").set_value("0"); + + auto line_style_list_node = format_scheme_node.append_child("a:lnStyleLst"); + + auto ln_node = line_style_list_node.append_child("a:ln"); + ln_node.append_attribute("w").set_value("9525"); + ln_node.append_attribute("cap").set_value("flat"); + ln_node.append_attribute("cmpd").set_value("sng"); + ln_node.append_attribute("algn").set_value("ctr"); + + auto solid_fill_node = ln_node.append_child("a:solidFill"); + scheme_color_node = solid_fill_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("95000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("105000"); + ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid"); + + ln_node = line_style_list_node.append_child("a:ln"); + ln_node.append_attribute("w").set_value("25400"); + ln_node.append_attribute("cap").set_value("flat"); + ln_node.append_attribute("cmpd").set_value("sng"); + ln_node.append_attribute("algn").set_value("ctr"); + + solid_fill_node = ln_node.append_child("a:solidFill"); + scheme_color_node = solid_fill_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid"); + + ln_node = line_style_list_node.append_child("a:ln"); + ln_node.append_attribute("w").set_value("38100"); + ln_node.append_attribute("cap").set_value("flat"); + ln_node.append_attribute("cmpd").set_value("sng"); + ln_node.append_attribute("algn").set_value("ctr"); + + solid_fill_node = ln_node.append_child("a:solidFill"); + scheme_color_node = solid_fill_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + ln_node.append_child("a:prstDash").append_attribute("val").set_value("solid"); + + auto effect_style_list_node = format_scheme_node.append_child("a:effectStyleLst"); + auto effect_style_node = effect_style_list_node.append_child("a:effectStyle"); + auto effect_list_node = effect_style_node.append_child("a:effectLst"); + auto outer_shadow_node = effect_list_node.append_child("a:outerShdw"); + outer_shadow_node.append_attribute("blurRad").set_value("40000"); + outer_shadow_node.append_attribute("dist").set_value("20000"); + outer_shadow_node.append_attribute("dir").set_value("5400000"); + outer_shadow_node.append_attribute("rotWithShape").set_value("0"); + auto srgb_clr_node = outer_shadow_node.append_child("a:srgbClr"); + srgb_clr_node.append_attribute("val").set_value("000000"); + srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value("38000"); + + effect_style_node = effect_style_list_node.append_child("a:effectStyle"); + effect_list_node = effect_style_node.append_child("a:effectLst"); + outer_shadow_node = effect_list_node.append_child("a:outerShdw"); + outer_shadow_node.append_attribute("blurRad").set_value("40000"); + outer_shadow_node.append_attribute("dist").set_value("23000"); + outer_shadow_node.append_attribute("dir").set_value("5400000"); + outer_shadow_node.append_attribute("rotWithShape").set_value("0"); + srgb_clr_node = outer_shadow_node.append_child("a:srgbClr"); + srgb_clr_node.append_attribute("val").set_value("000000"); + srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value("35000"); + + effect_style_node = effect_style_list_node.append_child("a:effectStyle"); + effect_list_node = effect_style_node.append_child("a:effectLst"); + outer_shadow_node = effect_list_node.append_child("a:outerShdw"); + outer_shadow_node.append_attribute("blurRad").set_value("40000"); + outer_shadow_node.append_attribute("dist").set_value("23000"); + outer_shadow_node.append_attribute("dir").set_value("5400000"); + outer_shadow_node.append_attribute("rotWithShape").set_value("0"); + srgb_clr_node = outer_shadow_node.append_child("a:srgbClr"); + srgb_clr_node.append_attribute("val").set_value("000000"); + srgb_clr_node.append_child("a:alpha").append_attribute("val").set_value("35000"); + auto scene3d_node = effect_style_node.append_child("a:scene3d"); + auto camera_node = scene3d_node.append_child("a:camera"); + camera_node.append_attribute("prst").set_value("orthographicFront"); + auto rot_node = camera_node.append_child("a:rot"); + rot_node.append_attribute("lat").set_value("0"); + rot_node.append_attribute("lon").set_value("0"); + rot_node.append_attribute("rev").set_value("0"); + auto light_rig_node = scene3d_node.append_child("a:lightRig"); + light_rig_node.append_attribute("rig").set_value("threePt"); + light_rig_node.append_attribute("dir").set_value("t"); + rot_node = light_rig_node.append_child("a:rot"); + rot_node.append_attribute("lat").set_value("0"); + rot_node.append_attribute("lon").set_value("0"); + rot_node.append_attribute("rev").set_value("1200000"); + + auto bevel_node = effect_style_node.append_child("a:sp3d").append_child("a:bevelT"); + bevel_node.append_attribute("w").set_value("63500"); + bevel_node.append_attribute("h").set_value("25400"); + + auto bg_fill_style_list_node = format_scheme_node.append_child("a:bgFillStyleLst"); + + bg_fill_style_list_node.append_child("a:solidFill").append_child("a:schemeClr").append_attribute("val").set_value("phClr"); + + grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill"); + grad_fill_node.append_attribute("rotWithShape").set_value("1"); + + grad_fill_list = grad_fill_node.append_child("a:gsLst"); + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("0"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("40000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("350000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("40000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("45000"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("99000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("350000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("100000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("20000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("255000"); + + auto path_node = grad_fill_node.append_child("a:path"); + path_node.append_attribute("path").set_value("circle"); + auto fill_to_rect_node = path_node.append_child("a:fillToRect"); + fill_to_rect_node.append_attribute("l").set_value("50000"); + fill_to_rect_node.append_attribute("t").set_value("-80000"); + fill_to_rect_node.append_attribute("r").set_value("50000"); + fill_to_rect_node.append_attribute("b").set_value("180000"); + + grad_fill_node = bg_fill_style_list_node.append_child("a:gradFill"); + grad_fill_node.append_attribute("rotWithShape").set_value("1"); + + grad_fill_list = grad_fill_node.append_child("a:gsLst"); + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("0"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:tint").append_attribute("val").set_value("80000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("300000"); + + gs_node = grad_fill_list.append_child("a:gs"); + gs_node.append_attribute("pos").set_value("100000"); + scheme_color_node = gs_node.append_child("a:schemeClr"); + scheme_color_node.append_attribute("val").set_value("phClr"); + scheme_color_node.append_child("a:shade").append_attribute("val").set_value("30000"); + scheme_color_node.append_child("a:satMod").append_attribute("val").set_value("200000"); + + path_node = grad_fill_node.append_child("a:path"); + path_node.append_attribute("path").set_value("circle"); + fill_to_rect_node = path_node.append_child("a:fillToRect"); + fill_to_rect_node.append_attribute("l").set_value("50000"); + fill_to_rect_node.append_attribute("t").set_value("50000"); + fill_to_rect_node.append_attribute("r").set_value("50000"); + fill_to_rect_node.append_attribute("b").set_value("50000"); + + theme_node.append_child("a:objectDefaults"); + theme_node.append_child("a:extraClrSchemeLst"); +} + +} // namespace xlnt diff --git a/include/xlnt/serialization/theme_serializer.hpp b/source/detail/theme_serializer.hpp similarity index 90% rename from include/xlnt/serialization/theme_serializer.hpp rename to source/detail/theme_serializer.hpp index 410cdec9..ea945e6a 100644 --- a/include/xlnt/serialization/theme_serializer.hpp +++ b/source/detail/theme_serializer.hpp @@ -27,10 +27,13 @@ #include +namespace pugi { +class xml_document; +} // namespace pugi + namespace xlnt { class theme; -class xml_document; /// /// Manages converting a theme to and from XML. @@ -38,8 +41,8 @@ class xml_document; class XLNT_CLASS theme_serializer { public: - bool read_theme(const xml_document &xml, theme &t); - xml_document write_theme(const theme &t) const; + bool read_theme(const pugi::xml_document &xml, theme &t); + void write_theme(const theme &t, pugi::xml_document &xml) const; private: }; diff --git a/source/detail/workbook_impl.hpp b/source/detail/workbook_impl.hpp index 00888f25..3534ec48 100644 --- a/source/detail/workbook_impl.hpp +++ b/source/detail/workbook_impl.hpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include diff --git a/source/detail/workbook_serializer.cpp b/source/detail/workbook_serializer.cpp new file mode 100644 index 00000000..ed1378d7 --- /dev/null +++ b/source/detail/workbook_serializer.cpp @@ -0,0 +1,331 @@ +// Copyright (c) 2014-2016 Thomas Fussell +// Copyright (c) 2010-2015 openpyxl +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +xlnt::datetime w3cdtf_to_datetime(const std::string &string) +{ + xlnt::datetime result(1900, 1, 1); + auto separator_index = string.find('-'); + result.year = std::stoi(string.substr(0, separator_index)); + result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1))); + separator_index = string.find('-', separator_index + 1); + result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1))); + separator_index = string.find('T', separator_index + 1); + result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); + separator_index = string.find(':', separator_index + 1); + result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); + separator_index = string.find(':', separator_index + 1); + result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1))); + return result; +} + +std::string fill(const std::string &string, std::size_t length = 2) +{ + if (string.size() >= length) + { + return string; + } + + return std::string(length - string.size(), '0') + string; +} + +std::string datetime_to_w3cdtf(const xlnt::datetime &dt) +{ + return std::to_string(dt.year) + "-" + fill(std::to_string(dt.month)) + "-" + fill(std::to_string(dt.day)) + "T" + + fill(std::to_string(dt.hour)) + ":" + fill(std::to_string(dt.minute)) + ":" + + fill(std::to_string(dt.second)) + "Z"; +} + +} // namespace + +namespace xlnt { + +workbook_serializer::workbook_serializer(workbook &wb) : workbook_(wb) +{ +} + +void workbook_serializer::read_properties_core(const pugi::xml_document &xml) +{ + auto &props = workbook_.get_properties(); + auto root_node = xml.child("cp:coreProperties"); + + props.excel_base_date = calendar::windows_1900; + + if (root_node.child("dc:creator")) + { + props.creator = root_node.child("dc:creator").text().get(); + } + + if (root_node.child("cp:lastModifiedBy")) + { + props.last_modified_by = root_node.child("cp:lastModifiedBy").text().get(); + } + + if (root_node.child("dcterms:created")) + { + std::string created_string = root_node.child("dcterms:created").text().get(); + props.created = w3cdtf_to_datetime(created_string); + } + + if (root_node.child("dcterms:modified")) + { + std::string modified_string = root_node.child("dcterms:modified").text().get(); + props.modified = w3cdtf_to_datetime(modified_string); + } +} + +void workbook_serializer::read_properties_app(const pugi::xml_document &xml) +{ + auto &props = workbook_.get_app_properties(); + auto root_node = xml.child("Properties"); + + if(root_node.child("Application")) + { + props.application = root_node.child("Application").text().get(); + } + + if(root_node.child("DocSecurity")) + { + props.doc_security = std::stoi(root_node.child("DocSecurity").text().get()); + } + + if(root_node.child("ScaleCrop")) + { + props.scale_crop = root_node.child("ScaleCrop").text().get() == std::string("true"); + } + + if(root_node.child("Company")) + { + props.company = root_node.child("Company").text().get(); + } + + if(root_node.child("ScaleCrop")) + { + props.links_up_to_date = root_node.child("ScaleCrop").text().get() == std::string("true"); + } + + if(root_node.child("SharedDoc")) + { + props.shared_doc = root_node.child("SharedDoc").text().get() == std::string("true"); + } + + if(root_node.child("HyperlinksChanged")) + { + props.hyperlinks_changed = root_node.child("HyperlinksChanged").text().get() == std::string("true"); + } + + if(root_node.child("AppVersion")) + { + props.app_version = root_node.child("AppVersion").text().get(); + } +} + +void workbook_serializer::write_properties_core(pugi::xml_document &xml) const +{ + auto &props = workbook_.get_properties(); + auto root_node = xml.append_child("cp:coreProperties"); + + root_node.append_attribute("xmlns:cp").set_value("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + root_node.append_attribute("xmlns:dc").set_value("http://purl.org/dc/elements/1.1/"); + root_node.append_attribute("xmlns:dcmitype").set_value("http://purl.org/dc/dcmitype/"); + root_node.append_attribute("xmlns:dcterms").set_value("http://purl.org/dc/terms/"); + root_node.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance"); + + root_node.append_child("dc:creator").text().set(props.creator.c_str()); + root_node.append_child("cp:lastModifiedBy").text().set(props.last_modified_by.c_str()); + root_node.append_child("dcterms:created").text().set(datetime_to_w3cdtf(props.created).c_str()); + root_node.child("dcterms:created").append_attribute("xsi:type").set_value("dcterms:W3CDTF"); + root_node.append_child("dcterms:modified").text().set(datetime_to_w3cdtf(props.modified).c_str()); + root_node.child("dcterms:modified").append_attribute("xsi:type").set_value("dcterms:W3CDTF"); + root_node.append_child("dc:title").text().set(props.title.c_str()); + root_node.append_child("dc:description"); + root_node.append_child("dc:subject"); + root_node.append_child("cp:keywords"); + root_node.append_child("cp:category"); +} + +void workbook_serializer::write_properties_app(pugi::xml_document &xml) const +{ + auto root_node = xml.append_child("Properties"); + + root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); + root_node.append_attribute("xmlns:vt").set_value("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + + auto &properties = workbook_.get_app_properties(); + + root_node.append_child("Application").text().set(properties.application.c_str()); + root_node.append_child("DocSecurity").text().set(std::to_string(properties.doc_security).c_str()); + root_node.append_child("ScaleCrop").text().set(properties.scale_crop ? "true" : "false"); + + auto company_node = root_node.append_child("Company"); + + if (!properties.company.empty()) + { + company_node.text().set(properties.company.c_str()); + } + + root_node.append_child("LinksUpToDate").text().set(properties.links_up_to_date ? "true" : "false"); + root_node.append_child("SharedDoc").text().set(properties.shared_doc ? "true" : "false"); + root_node.append_child("HyperlinksChanged").text().set(properties.hyperlinks_changed ? "true" : "false"); + root_node.append_child("AppVersion").text().set(properties.app_version.c_str()); + + // TODO what is this stuff? + + auto heading_pairs_node = root_node.append_child("HeadingPairs"); + auto heading_pairs_vector_node = heading_pairs_node.append_child("vt:vector"); + heading_pairs_vector_node.append_attribute("size").set_value("2"); + heading_pairs_vector_node.append_attribute("baseType").set_value("variant"); + heading_pairs_vector_node.append_child("vt:variant").append_child("vt:lpstr").text().set("Worksheets"); + heading_pairs_vector_node.append_child("vt:variant") + .append_child("vt:i4") + .text().set(std::to_string(workbook_.get_sheet_names().size()).c_str()); + + auto titles_of_parts_node = root_node.append_child("TitlesOfParts"); + auto titles_of_parts_vector_node = titles_of_parts_node.append_child("vt:vector"); + titles_of_parts_vector_node.append_attribute("size").set_value(std::to_string(workbook_.get_sheet_names().size()).c_str()); + titles_of_parts_vector_node.append_attribute("baseType").set_value("lpstr"); + + for (auto ws : workbook_) + { + titles_of_parts_vector_node.append_child("vt:lpstr").text().set(ws.get_title().c_str()); + } +} + +void workbook_serializer::write_workbook(pugi::xml_document &xml) const +{ + std::size_t num_visible = 0; + + for (auto ws : workbook_) + { + if (ws.get_page_setup().get_sheet_state() == sheet_state::visible) + { + num_visible++; + } + } + + if (num_visible == 0) + { + throw xlnt::value_error(); + } + + auto root_node = xml.append_child("workbook"); + + root_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + root_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + + auto file_version_node = root_node.append_child("fileVersion"); + file_version_node.append_attribute("appName").set_value("xl"); + file_version_node.append_attribute("lastEdited").set_value("4"); + file_version_node.append_attribute("lowestEdited").set_value("4"); + file_version_node.append_attribute("rupBuild").set_value("4505"); + + auto workbook_pr_node = root_node.append_child("workbookPr"); + workbook_pr_node.append_attribute("codeName").set_value("ThisWorkbook"); + workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226"); + workbook_pr_node.append_attribute("date1904").set_value(workbook_.get_properties().excel_base_date == calendar::mac_1904 ? "1" : "0"); + + auto book_views_node = root_node.append_child("bookViews"); + auto workbook_view_node = book_views_node.append_child("workbookView"); + workbook_view_node.append_attribute("activeTab").set_value("0"); + workbook_view_node.append_attribute("autoFilterDateGrouping").set_value("1"); + workbook_view_node.append_attribute("firstSheet").set_value("0"); + workbook_view_node.append_attribute("minimized").set_value("0"); + workbook_view_node.append_attribute("showHorizontalScroll").set_value("1"); + workbook_view_node.append_attribute("showSheetTabs").set_value("1"); + workbook_view_node.append_attribute("showVerticalScroll").set_value("1"); + workbook_view_node.append_attribute("tabRatio").set_value("600"); + workbook_view_node.append_attribute("visibility").set_value("visible"); + + auto sheets_node = root_node.append_child("sheets"); + auto defined_names_node = root_node.append_child("definedNames"); + + for (const auto &relationship : workbook_.get_relationships()) + { + if (relationship.get_type() == relationship::type::worksheet) + { + // TODO: this is ugly + std::string sheet_index_string = relationship.get_target_uri(); + sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.')); + sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/')); + auto iter = sheet_index_string.end(); + iter--; + while (isdigit(*iter)) + iter--; + auto first_digit = iter - sheet_index_string.begin(); + sheet_index_string = sheet_index_string.substr(static_cast(first_digit + 1)); + std::size_t sheet_index = static_cast(std::stoll(sheet_index_string) - 1); + + auto ws = workbook_.get_sheet_by_index(sheet_index); + + auto sheet_node = sheets_node.append_child("sheet"); + sheet_node.append_attribute("name").set_value(ws.get_title().c_str()); + sheet_node.append_attribute("sheetId").set_value(std::to_string(sheet_index + 1).c_str()); + sheet_node.append_attribute("r:id").set_value(relationship.get_id().c_str()); + + if (ws.has_auto_filter()) + { + auto defined_name_node = defined_names_node.append_child("definedName"); + defined_name_node.append_attribute("name").set_value("_xlnm._FilterDatabase"); + defined_name_node.append_attribute("hidden").set_value("1"); + defined_name_node.append_attribute("localSheetId").set_value("0"); + std::string name = + "'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string(); + defined_name_node.text().set(name.c_str()); + } + } + } + + auto calc_pr_node = root_node.append_child("calcPr"); + calc_pr_node.append_attribute("calcId").set_value("124519"); + calc_pr_node.append_attribute("calcMode").set_value("auto"); + calc_pr_node.append_attribute("fullCalcOnLoad").set_value("1"); +} + +void workbook_serializer::write_named_ranges(pugi::xml_node node) const +{ + for (auto &named_range : workbook_.get_named_ranges()) + { + node.append_child(named_range.get_name().c_str()); + } +} + +} // namespace xlnt diff --git a/include/xlnt/serialization/workbook_serializer.hpp b/source/detail/workbook_serializer.hpp similarity index 79% rename from include/xlnt/serialization/workbook_serializer.hpp rename to source/detail/workbook_serializer.hpp index cd704845..d56b34cc 100644 --- a/include/xlnt/serialization/workbook_serializer.hpp +++ b/source/detail/workbook_serializer.hpp @@ -28,6 +28,11 @@ #include +namespace pugi { +class xml_document; +class xml_node; +} // namespace pugi + namespace xlnt { class document_properties; @@ -36,8 +41,6 @@ class relationship; class worksheet; class workbook; class zip_file; -class xml_document; -class xml_node; /// /// Manages converting workbook to and from XML. @@ -49,15 +52,15 @@ public: workbook_serializer(workbook &wb); - void read_workbook(const xml_document &xml); - void read_properties_app(const xml_document &xml); - void read_properties_core(const xml_document &xml); + void read_workbook(const pugi::xml_document &xml); + void read_properties_app(const pugi::xml_document &xml); + void read_properties_core(const pugi::xml_document &xml); - xml_document write_workbook() const; - xml_document write_properties_app() const; - xml_document write_properties_core() const; + void write_workbook(pugi::xml_document &xml) const; + void write_properties_app(pugi::xml_document &xml) const; + void write_properties_core(pugi::xml_document &xml) const; - xml_node write_named_ranges() const; + void write_named_ranges(pugi::xml_node node) const; private: workbook &workbook_; diff --git a/source/serialization/worksheet_serializer.cpp b/source/detail/worksheet_serializer.cpp similarity index 53% rename from source/serialization/worksheet_serializer.cpp rename to source/detail/worksheet_serializer.cpp index 3061c634..58b766c6 100644 --- a/source/serialization/worksheet_serializer.cpp +++ b/source/detail/worksheet_serializer.cpp @@ -21,16 +21,18 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file + #include #include +#include #include -#include +#include +#include +#include #include #include #include -#include -#include #include #include #include @@ -39,9 +41,6 @@ #include #include -#include -#include - namespace { bool is_integral(long double d) @@ -57,28 +56,23 @@ worksheet_serializer::worksheet_serializer(worksheet sheet) : sheet_(sheet) { } -bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::stylesheet &stylesheet) +bool worksheet_serializer::read_worksheet(const pugi::xml_document &xml, detail::stylesheet &stylesheet) { - auto &root_node = xml.get_child("worksheet"); + auto root_node = xml.child("worksheet"); - auto &dimension_node = root_node.get_child("dimension"); - std::string dimension = dimension_node.get_attribute("ref"); + auto dimension_node = root_node.child("dimension"); + std::string dimension(dimension_node.attribute("ref").value()); auto full_range = xlnt::range_reference(dimension); - auto sheet_data_node = root_node.get_child("sheetData"); + auto sheet_data_node = root_node.child("sheetData"); - if (root_node.has_child("mergeCells")) + if (root_node.child("mergeCells")) { - auto merge_cells_node = root_node.get_child("mergeCells"); - auto count = std::stoull(merge_cells_node.get_attribute("count")); + auto merge_cells_node = root_node.child("mergeCells"); + auto count = std::stoull(merge_cells_node.attribute("count").value()); - for (auto merge_cell_node : merge_cells_node.get_children()) + for (auto merge_cell_node : merge_cells_node.children("mergeCell")) { - if (merge_cell_node.get_name() != "mergeCell") - { - continue; - } - - sheet_.merge_cells(range_reference(merge_cell_node.get_attribute("ref"))); + sheet_.merge_cells(range_reference(merge_cell_node.attribute("ref").value())); count--; } @@ -90,21 +84,16 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::style auto &shared_strings = sheet_.get_workbook().get_shared_strings(); - for (auto row_node : sheet_data_node.get_children()) + for (auto row_node : sheet_data_node.children("row")) { - if (row_node.get_name() != "row") + auto row_index = static_cast(std::stoull(row_node.attribute("r").value())); + + if (row_node.attribute("ht")) { - continue; + sheet_.get_row_properties(row_index).height = std::stold(row_node.attribute("ht").value()); } - auto row_index = static_cast(std::stoull(row_node.get_attribute("r"))); - - if (row_node.has_attribute("ht")) - { - sheet_.get_row_properties(row_index).height = std::stold(row_node.get_attribute("ht")); - } - - std::string span_string = row_node.get_attribute("spans"); + std::string span_string = row_node.attribute("spans").value(); auto colon_index = span_string.find(':'); column_t min_column = 0; @@ -125,17 +114,12 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::style { std::string address = i.column_string() + std::to_string(row_index); - xml_node cell_node; + pugi::xml_node cell_node; bool cell_found = false; - for (auto &check_cell_node : row_node.get_children()) + for (auto &check_cell_node : row_node.children("c")) { - if (check_cell_node.get_name() != "c") - { - continue; - } - - if (check_cell_node.has_attribute("r") && check_cell_node.get_attribute("r") == address) + if (check_cell_node.attribute("r") && check_cell_node.attribute("r").value() == address) { cell_node = check_cell_node; cell_found = true; @@ -145,30 +129,30 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::style if (cell_found) { - bool has_value = cell_node.has_child("v"); - std::string value_string = has_value ? cell_node.get_child("v").get_text() : ""; + bool has_value = cell_node.child("v"); + std::string value_string = has_value ? cell_node.child("v").text().get() : ""; - bool has_type = cell_node.has_attribute("t"); - std::string type = has_type ? cell_node.get_attribute("t") : ""; + bool has_type = cell_node.attribute("t"); + std::string type = has_type ? cell_node.attribute("t").value() : ""; - bool has_format = cell_node.has_attribute("s"); - auto format_id = static_cast(has_format ? std::stoull(cell_node.get_attribute("s")) : 0LL); + bool has_format = cell_node.attribute("s"); + auto format_id = static_cast(has_format ? std::stoull(cell_node.attribute("s").value()) : 0LL); - bool has_formula = cell_node.has_child("f"); - bool has_shared_formula = has_formula && cell_node.get_child("f").has_attribute("t") && - cell_node.get_child("f").get_attribute("t") == "shared"; + bool has_formula = cell_node.child("f"); + bool has_shared_formula = has_formula && cell_node.child("f").attribute("t") + && cell_node.child("f").attribute("t").value() == std::string("shared"); auto cell = sheet_.get_cell(address); if (has_formula && !has_shared_formula && !sheet_.get_workbook().get_data_only()) { - std::string formula = cell_node.get_child("f").get_text(); + std::string formula = cell_node.child("f").text().get(); cell.set_formula(formula); } if (has_type && type == "inlineStr") // inline string { - std::string inline_string = cell_node.get_child("is").get_child("t").get_text(); + std::string inline_string = cell_node.child("is").child("t").text().get(); cell.set_value(inline_string); } else if (has_type && type == "s" && !has_formula) // shared string @@ -205,20 +189,15 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::style } } - auto &cols_node = root_node.get_child("cols"); + auto cols_node = root_node.child("cols"); - for (auto col_node : cols_node.get_children()) + for (auto col_node : cols_node.children("col")) { - if (col_node.get_name() != "col") - { - continue; - } - - auto min = static_cast(std::stoull(col_node.get_attribute("min"))); - auto max = static_cast(std::stoull(col_node.get_attribute("max"))); - auto width = std::stold(col_node.get_attribute("width")); - bool custom = col_node.get_attribute("customWidth") == "1"; - auto column_style = static_cast(col_node.has_attribute("style") ? std::stoull(col_node.get_attribute("style")) : 0); + auto min = static_cast(std::stoull(col_node.attribute("min").value())); + auto max = static_cast(std::stoull(col_node.attribute("max").value())); + auto width = std::stold(col_node.attribute("width").value()); + bool custom = col_node.attribute("customWidth").value() == std::string("1"); + auto column_style = static_cast(col_node.attribute("style") ? std::stoull(col_node.attribute("style").value()) : 0); for (auto column = min; column <= max; column++) { @@ -233,102 +212,100 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::style } } - if (root_node.has_child("autoFilter")) + if (root_node.child("autoFilter")) { - auto &auto_filter_node = root_node.get_child("autoFilter"); - xlnt::range_reference ref(auto_filter_node.get_attribute("ref")); + auto auto_filter_node = root_node.child("autoFilter"); + xlnt::range_reference ref(auto_filter_node.attribute("ref").value()); sheet_.auto_filter(ref); } return true; } -xml_document worksheet_serializer::write_worksheet() const +void worksheet_serializer::write_worksheet(pugi::xml_document &xml) const { - xml_document xml; + auto root_node = xml.append_child("worksheet"); - auto root_node = xml.add_child("worksheet"); + root_node.append_attribute("xmlns").set_value(constants::Namespace("spreadsheetml").c_str()); + root_node.append_attribute("xmlns:r").set_value(constants::Namespace("r").c_str()); - xml.add_namespace("", constants::Namespace("spreadsheetml")); - xml.add_namespace("r", constants::Namespace("r")); + auto sheet_pr_node = root_node.append_child("sheetPr"); - auto sheet_pr_node = root_node.add_child("sheetPr"); + auto outline_pr_node = sheet_pr_node.append_child("outlinePr"); - auto outline_pr_node = sheet_pr_node.add_child("outlinePr"); - - outline_pr_node.add_attribute("summaryBelow", "1"); - outline_pr_node.add_attribute("summaryRight", "1"); + outline_pr_node.append_attribute("summaryBelow").set_value("1"); + outline_pr_node.append_attribute("summaryRight").set_value("1"); if (!sheet_.get_page_setup().is_default()) { - auto page_set_up_pr_node = sheet_pr_node.add_child("pageSetUpPr"); - page_set_up_pr_node.add_attribute("fitToPage", sheet_.get_page_setup().fit_to_page() ? "1" : "0"); + auto page_set_up_pr_node = sheet_pr_node.append_child("pageSetUpPr"); + page_set_up_pr_node.append_attribute("fitToPage").set_value(sheet_.get_page_setup().fit_to_page() ? "1" : "0"); } - auto dimension_node = root_node.add_child("dimension"); - dimension_node.add_attribute("ref", sheet_.calculate_dimension().to_string()); + auto dimension_node = root_node.append_child("dimension"); + dimension_node.append_attribute("ref").set_value(sheet_.calculate_dimension().to_string().c_str()); - auto sheet_views_node = root_node.add_child("sheetViews"); - auto sheet_view_node = sheet_views_node.add_child("sheetView"); - sheet_view_node.add_attribute("workbookViewId", "0"); + auto sheet_views_node = root_node.append_child("sheetViews"); + auto sheet_view_node = sheet_views_node.append_child("sheetView"); + sheet_view_node.append_attribute("workbookViewId").set_value("0"); std::string active_pane = "bottomRight"; if (sheet_.has_frozen_panes()) { - auto pane_node = sheet_view_node.add_child("pane"); + auto pane_node = sheet_view_node.append_child("pane"); if (sheet_.get_frozen_panes().get_column_index() > 1) { - pane_node.add_attribute("xSplit", std::to_string(sheet_.get_frozen_panes().get_column_index().index - 1)); + pane_node.append_attribute("xSplit").set_value(std::to_string(sheet_.get_frozen_panes().get_column_index().index - 1).c_str()); active_pane = "topRight"; } if (sheet_.get_frozen_panes().get_row() > 1) { - pane_node.add_attribute("ySplit", std::to_string(sheet_.get_frozen_panes().get_row() - 1)); + pane_node.append_attribute("ySplit").set_value(std::to_string(sheet_.get_frozen_panes().get_row() - 1).c_str()); active_pane = "bottomLeft"; } if (sheet_.get_frozen_panes().get_row() > 1 && sheet_.get_frozen_panes().get_column_index() > 1) { - auto top_right_node = sheet_view_node.add_child("selection"); - top_right_node.add_attribute("pane", "topRight"); - auto bottom_left_node = sheet_view_node.add_child("selection"); - bottom_left_node.add_attribute("pane", "bottomLeft"); + auto top_right_node = sheet_view_node.append_child("selection"); + top_right_node.append_attribute("pane").set_value("topRight"); + auto bottom_left_node = sheet_view_node.append_child("selection"); + bottom_left_node.append_attribute("pane").set_value("bottomLeft"); active_pane = "bottomRight"; } - pane_node.add_attribute("topLeftCell", sheet_.get_frozen_panes().to_string()); - pane_node.add_attribute("activePane", active_pane); - pane_node.add_attribute("state", "frozen"); + pane_node.append_attribute("topLeftCell").set_value(sheet_.get_frozen_panes().to_string().c_str()); + pane_node.append_attribute("activePane").set_value(active_pane.c_str()); + pane_node.append_attribute("state").set_value("frozen"); } - auto selection_node = sheet_view_node.add_child("selection"); + auto selection_node = sheet_view_node.append_child("selection"); if (sheet_.has_frozen_panes()) { if (sheet_.get_frozen_panes().get_row() > 1 && sheet_.get_frozen_panes().get_column_index() > 1) { - selection_node.add_attribute("pane", "bottomRight"); + selection_node.append_attribute("pane").set_value("bottomRight"); } else if (sheet_.get_frozen_panes().get_row() > 1) { - selection_node.add_attribute("pane", "bottomLeft"); + selection_node.append_attribute("pane").set_value("bottomLeft"); } else if (sheet_.get_frozen_panes().get_column_index() > 1) { - selection_node.add_attribute("pane", "topRight"); + selection_node.append_attribute("pane").set_value("topRight"); } } std::string active_cell = "A1"; - selection_node.add_attribute("activeCell", active_cell); - selection_node.add_attribute("sqref", active_cell); + selection_node.append_attribute("activeCell").set_value(active_cell.c_str()); + selection_node.append_attribute("sqref").set_value(active_cell.c_str()); - auto sheet_format_pr_node = root_node.add_child("sheetFormatPr"); - sheet_format_pr_node.add_attribute("baseColWidth", "10"); - sheet_format_pr_node.add_attribute("defaultRowHeight", "15"); + auto sheet_format_pr_node = root_node.append_child("sheetFormatPr"); + sheet_format_pr_node.append_attribute("baseColWidth").set_value("10"); + sheet_format_pr_node.append_attribute("defaultRowHeight").set_value("15"); bool has_column_properties = false; @@ -343,7 +320,7 @@ xml_document worksheet_serializer::write_worksheet() const if (has_column_properties) { - auto cols_node = root_node.add_child("cols"); + auto cols_node = root_node.append_child("cols"); for (auto column = sheet_.get_lowest_column(); column <= sheet_.get_highest_column(); column++) { @@ -354,19 +331,19 @@ xml_document worksheet_serializer::write_worksheet() const const auto &props = sheet_.get_column_properties(column); - auto col_node = cols_node.add_child("col"); + auto col_node = cols_node.append_child("col"); - col_node.add_attribute("min", std::to_string(column.index)); - col_node.add_attribute("max", std::to_string(column.index)); - col_node.add_attribute("width", std::to_string(props.width)); - col_node.add_attribute("style", std::to_string(props.style)); - col_node.add_attribute("customWidth", props.custom ? "1" : "0"); + col_node.append_attribute("min").set_value(std::to_string(column.index).c_str()); + col_node.append_attribute("max").set_value(std::to_string(column.index).c_str()); + col_node.append_attribute("width").set_value(std::to_string(props.width).c_str()); + col_node.append_attribute("style").set_value(std::to_string(props.style).c_str()); + col_node.append_attribute("customWidth").set_value(props.custom ? "1" : "0"); } } std::unordered_map hyperlink_references; - auto sheet_data_node = root_node.add_child("sheetData"); + auto sheet_data_node = root_node.append_child("sheetData"); const auto &shared_strings = sheet_.get_workbook().get_shared_strings(); for (auto row : sheet_.rows()) @@ -391,27 +368,27 @@ xml_document worksheet_serializer::write_worksheet() const continue; } - auto row_node = sheet_data_node.add_child("row"); + auto row_node = sheet_data_node.append_child("row"); - row_node.add_attribute("r", std::to_string(row.front().get_row())); - row_node.add_attribute("spans", (std::to_string(min) + ":" + std::to_string(max))); + row_node.append_attribute("r").set_value(std::to_string(row.front().get_row()).c_str()); + row_node.append_attribute("spans").set_value((std::to_string(min) + ":" + std::to_string(max)).c_str()); if (sheet_.has_row_properties(row.front().get_row())) { - row_node.add_attribute("customHeight", "1"); + row_node.append_attribute("customHeight").set_value("1"); auto height = sheet_.get_row_properties(row.front().get_row()).height; if (height == std::floor(height)) { - row_node.add_attribute("ht", std::to_string(static_cast(height)) + ".0"); + row_node.append_attribute("ht").set_value((std::to_string(static_cast(height)) + ".0").c_str()); } else { - row_node.add_attribute("ht", std::to_string(height)); + row_node.append_attribute("ht").set_value(std::to_string(height).c_str()); } } - // row_node.add_attribute("x14ac:dyDescent", 0.25); + // row_node.append_attribute("x14ac:dyDescent", 0.25); for (auto cell : row) { @@ -422,16 +399,16 @@ xml_document worksheet_serializer::write_worksheet() const hyperlink_references[cell.get_hyperlink().get_id()] = cell.get_reference().to_string(); } - auto cell_node = row_node.add_child("c"); - cell_node.add_attribute("r", cell.get_reference().to_string()); + auto cell_node = row_node.append_child("c"); + cell_node.append_attribute("r").set_value(cell.get_reference().to_string().c_str()); if (cell.get_data_type() == cell::type::string) { if (cell.has_formula()) { - cell_node.add_attribute("t", "str"); - cell_node.add_child("f").set_text(cell.get_formula()); - cell_node.add_child("v").set_text(cell.to_string()); + cell_node.append_attribute("t").set_value("str"); + cell_node.append_child("f").text().set(cell.get_formula().c_str()); + cell_node.append_child("v").text().set(cell.to_string().c_str()); continue; } @@ -451,20 +428,20 @@ xml_document worksheet_serializer::write_worksheet() const { if (cell.get_value().empty()) { - cell_node.add_attribute("t", "s"); + cell_node.append_attribute("t").set_value("s"); } else { - cell_node.add_attribute("t", "inlineStr"); - auto inline_string_node = cell_node.add_child("is"); - inline_string_node.add_child("t").set_text(cell.get_value()); + cell_node.append_attribute("t").set_value("inlineStr"); + auto inline_string_node = cell_node.append_child("is"); + inline_string_node.append_child("t").text().set(cell.get_value().c_str()); } } else { - cell_node.add_attribute("t", "s"); - auto value_node = cell_node.add_child("v"); - value_node.set_text(std::to_string(match_index)); + cell_node.append_attribute("t").set_value("s"); + auto value_node = cell_node.append_child("v"); + value_node.text().set(std::to_string(match_index).c_str()); } } else @@ -473,25 +450,25 @@ xml_document worksheet_serializer::write_worksheet() const { if (cell.get_data_type() == cell::type::boolean) { - cell_node.add_attribute("t", "b"); - auto value_node = cell_node.add_child("v"); - value_node.set_text(cell.get_value() ? "1" : "0"); + cell_node.append_attribute("t").set_value("b"); + auto value_node = cell_node.append_child("v"); + value_node.text().set(cell.get_value() ? "1" : "0"); } else if (cell.get_data_type() == cell::type::numeric) { if (cell.has_formula()) { - cell_node.add_child("f").set_text(cell.get_formula()); - cell_node.add_child("v").set_text(cell.to_string()); + cell_node.append_child("f").text().set(cell.get_formula().c_str()); + cell_node.append_child("v").text().set(cell.to_string().c_str()); continue; } - cell_node.add_attribute("t", "n"); - auto value_node = cell_node.add_child("v"); + cell_node.append_attribute("t").set_value("n"); + auto value_node = cell_node.append_child("v"); if (is_integral(cell.get_value())) { - value_node.set_text(std::to_string(cell.get_value())); + value_node.text().set(std::to_string(cell.get_value()).c_str()); } else { @@ -499,21 +476,21 @@ xml_document worksheet_serializer::write_worksheet() const ss.precision(20); ss << cell.get_value(); ss.str(); - value_node.set_text(ss.str()); + value_node.text().set(ss.str().c_str()); } } } else if (cell.has_formula()) { - cell_node.add_child("f").set_text(cell.get_formula()); - cell_node.add_child("v"); + cell_node.append_child("f").text().set(cell.get_formula().c_str()); + cell_node.append_child("v"); continue; } } if (cell.has_format()) { - cell_node.add_attribute("s", std::to_string(cell.get_format_id())); + cell_node.append_attribute("s").set_value(std::to_string(cell.get_format_id()).c_str()); } } } @@ -521,45 +498,45 @@ xml_document worksheet_serializer::write_worksheet() const if (sheet_.has_auto_filter()) { - auto auto_filter_node = root_node.add_child("autoFilter"); - auto_filter_node.add_attribute("ref", sheet_.get_auto_filter().to_string()); + auto auto_filter_node = root_node.append_child("autoFilter"); + auto_filter_node.append_attribute("ref").set_value(sheet_.get_auto_filter().to_string().c_str()); } if (!sheet_.get_merged_ranges().empty()) { - auto merge_cells_node = root_node.add_child("mergeCells"); - merge_cells_node.add_attribute("count", std::to_string(sheet_.get_merged_ranges().size())); + auto merge_cells_node = root_node.append_child("mergeCells"); + merge_cells_node.append_attribute("count").set_value(std::to_string(sheet_.get_merged_ranges().size()).c_str()); for (auto merged_range : sheet_.get_merged_ranges()) { - auto merge_cell_node = merge_cells_node.add_child("mergeCell"); - merge_cell_node.add_attribute("ref", merged_range.to_string()); + auto merge_cell_node = merge_cells_node.append_child("mergeCell"); + merge_cell_node.append_attribute("ref").set_value(merged_range.to_string().c_str()); } } if (!sheet_.get_relationships().empty()) { - auto hyperlinks_node = root_node.add_child("hyperlinks"); + auto hyperlinks_node = root_node.append_child("hyperlinks"); for (const auto &relationship : sheet_.get_relationships()) { - auto hyperlink_node = hyperlinks_node.add_child("hyperlink"); - hyperlink_node.add_attribute("display", relationship.get_target_uri()); - hyperlink_node.add_attribute("ref", hyperlink_references.at(relationship.get_id())); - hyperlink_node.add_attribute("r:id", relationship.get_id()); + auto hyperlink_node = hyperlinks_node.append_child("hyperlink"); + hyperlink_node.append_attribute("display").set_value(relationship.get_target_uri().c_str()); + hyperlink_node.append_attribute("ref").set_value(hyperlink_references.at(relationship.get_id()).c_str()); + hyperlink_node.append_attribute("r:id").set_value(relationship.get_id().c_str()); } } if (!sheet_.get_page_setup().is_default()) { - auto print_options_node = root_node.add_child("printOptions"); - print_options_node.add_attribute("horizontalCentered", + auto print_options_node = root_node.append_child("printOptions"); + print_options_node.append_attribute("horizontalCentered").set_value( sheet_.get_page_setup().get_horizontal_centered() ? "1" : "0"); - print_options_node.add_attribute("verticalCentered", + print_options_node.append_attribute("verticalCentered").set_value( sheet_.get_page_setup().get_vertical_centered() ? "1" : "0"); } - auto page_margins_node = root_node.add_child("pageMargins"); + auto page_margins_node = root_node.append_child("pageMargins"); //TODO: there must be a better way to do this auto remove_trailing_zeros = [](const std::string &n) @@ -583,43 +560,41 @@ xml_document worksheet_serializer::write_worksheet() const return n.substr(0, index + 1); }; - page_margins_node.add_attribute("left", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_left()))); - page_margins_node.add_attribute("right", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_right()))); - page_margins_node.add_attribute("top", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_top()))); - page_margins_node.add_attribute("bottom", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_bottom()))); - page_margins_node.add_attribute("header", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_header()))); - page_margins_node.add_attribute("footer", remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_footer()))); + page_margins_node.append_attribute("left").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_left())).c_str()); + page_margins_node.append_attribute("right").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_right())).c_str()); + page_margins_node.append_attribute("top").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_top())).c_str()); + page_margins_node.append_attribute("bottom").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_bottom())).c_str()); + page_margins_node.append_attribute("header").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_header())).c_str()); + page_margins_node.append_attribute("footer").set_value(remove_trailing_zeros(std::to_string(sheet_.get_page_margins().get_footer())).c_str()); if (!sheet_.get_page_setup().is_default()) { - auto page_setup_node = root_node.add_child("pageSetup"); + auto page_setup_node = root_node.append_child("pageSetup"); std::string orientation_string = sheet_.get_page_setup().get_orientation() == orientation::landscape ? "landscape" : "portrait"; - page_setup_node.add_attribute("orientation", orientation_string); - page_setup_node.add_attribute("paperSize", - std::to_string(static_cast(sheet_.get_page_setup().get_paper_size()))); - page_setup_node.add_attribute("fitToHeight", sheet_.get_page_setup().fit_to_height() ? "1" : "0"); - page_setup_node.add_attribute("fitToWidth", sheet_.get_page_setup().fit_to_width() ? "1" : "0"); + page_setup_node.append_attribute("orientation").set_value(orientation_string.c_str()); + page_setup_node.append_attribute("paperSize").set_value( + std::to_string(static_cast(sheet_.get_page_setup().get_paper_size())).c_str()); + page_setup_node.append_attribute("fitToHeight").set_value(sheet_.get_page_setup().fit_to_height() ? "1" : "0"); + page_setup_node.append_attribute("fitToWidth").set_value(sheet_.get_page_setup().fit_to_width() ? "1" : "0"); } if (!sheet_.get_header_footer().is_default()) { - auto header_footer_node = root_node.add_child("headerFooter"); - auto odd_header_node = header_footer_node.add_child("oddHeader"); + auto header_footer_node = root_node.append_child("headerFooter"); + auto odd_header_node = header_footer_node.append_child("oddHeader"); std::string header_text = "&L&\"Calibri,Regular\"&K000000Left Header Text&C&\"Arial,Regular\"&6&K445566Center Header " "Text&R&\"Arial,Bold\"&8&K112233Right Header Text"; - odd_header_node.set_text(header_text); - auto odd_footer_node = header_footer_node.add_child("oddFooter"); + odd_header_node.text().set(header_text.c_str()); + auto odd_footer_node = header_footer_node.append_child("oddFooter"); std::string footer_text = "&L&\"Times New Roman,Regular\"&10&K445566Left Footer Text_x000D_And &D and &T&C&\"Times New " "Roman,Bold\"&12&K778899Center Footer Text &Z&F on &A&R&\"Times New Roman,Italic\"&14&KAABBCCRight Footer " "Text &P of &N"; - odd_footer_node.set_text(footer_text); + odd_footer_node.text().set(footer_text.c_str()); } - - return xml; } } // namespace xlnt diff --git a/include/xlnt/serialization/worksheet_serializer.hpp b/source/detail/worksheet_serializer.hpp similarity index 90% rename from include/xlnt/serialization/worksheet_serializer.hpp rename to source/detail/worksheet_serializer.hpp index 6ebb410d..c9179c11 100644 --- a/include/xlnt/serialization/worksheet_serializer.hpp +++ b/source/detail/worksheet_serializer.hpp @@ -29,12 +29,15 @@ #include #include +namespace pugi { +class xml_document; +} // namespace pugi + namespace xlnt { class relationship; class workbook; class worksheet; -class xml_document; namespace detail { struct stylesheet; } @@ -46,8 +49,8 @@ class XLNT_CLASS worksheet_serializer public: worksheet_serializer(worksheet sheet); - bool read_worksheet(const xml_document &xml, detail::stylesheet &stylesheet); - xml_document write_worksheet() const; + bool read_worksheet(const pugi::xml_document &xml, detail::stylesheet &stylesheet); + void write_worksheet(pugi::xml_document &xml) const; private: worksheet sheet_; diff --git a/source/detail/xml_document_impl.hpp b/source/detail/xml_document_impl.hpp deleted file mode 100644 index b2097f60..00000000 --- a/source/detail/xml_document_impl.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include - -#include - -namespace xlnt { -namespace detail { - -struct xml_document_impl -{ - std::string encoding; - pugi::xml_document doc; -}; - -} // namespace detail -} // namespace xlnt diff --git a/source/detail/xml_node_impl.hpp b/source/detail/xml_node_impl.hpp deleted file mode 100644 index a159c8b8..00000000 --- a/source/detail/xml_node_impl.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include - -namespace xlnt { -namespace detail { - -struct xml_node_impl -{ - xml_node_impl() - { - } - - explicit xml_node_impl(pugi::xml_node n) : node(n) - { - } - - pugi::xml_node node; -}; - -} // namespace detail -} // namespace xlnt diff --git a/source/packaging/tests/test_core.hpp b/source/packaging/tests/test_core.hpp index ca56b594..1d8fd9aa 100644 --- a/source/packaging/tests/test_core.hpp +++ b/source/packaging/tests/test_core.hpp @@ -4,8 +4,7 @@ #include #include -#include -#include +#include #include #include @@ -48,7 +47,7 @@ public: auto content = archive.read("docProps/core.xml"); xlnt::workbook wb; xlnt::workbook_serializer serializer(wb); - xlnt::xml_document xml; + pugi::xml_document xml; serializer.read_properties_core(xml); auto &prop = wb.get_properties(); TS_ASSERT_EQUALS(prop.excel_base_date, xlnt::calendar::windows_1900); @@ -80,7 +79,8 @@ public: prop.created = xlnt::datetime(2010, 4, 1, 20, 30, 00); prop.modified = xlnt::datetime(2010, 4, 5, 14, 5, 30); xlnt::workbook_serializer serializer(wb); - xlnt::xml_document xml = serializer.write_properties_core(); + pugi::xml_document xml; + serializer.write_properties_core(xml); TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/core.xml", xml)); } @@ -92,7 +92,8 @@ public: wb.create_sheet(); wb.create_sheet(); xlnt::workbook_serializer serializer(wb); - xlnt::xml_document xml = serializer.write_properties_app(); + pugi::xml_document xml; + serializer.write_properties_app(xml); TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", xml)); } }; diff --git a/source/serialization/theme_serializer.cpp b/source/serialization/theme_serializer.cpp deleted file mode 100644 index e726c077..00000000 --- a/source/serialization/theme_serializer.cpp +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// Copyright (c) 2010-2015 openpyxl -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#include -#include -#include - -#include - -namespace xlnt { - -// I have no idea what this stuff is. I hope it was worth it. -xml_document theme_serializer::write_theme(const theme &) const -{ - xml_document xml; - - auto theme_node = xml.add_child("a:theme"); - xml.add_namespace("a", constants::Namespace("drawingml")); - theme_node.add_attribute("name", "Office Theme"); - - auto theme_elements_node = theme_node.add_child("a:themeElements"); - auto clr_scheme_node = theme_elements_node.add_child("a:clrScheme"); - clr_scheme_node.add_attribute("name", "Office"); - - struct scheme_element - { - std::string name; - std::string sub_element_name; - std::string val; - }; - - std::vector scheme_elements = { - { "a:dk1", "a:sysClr", "windowText" }, { "a:lt1", "a:sysClr", "window" }, - { "a:dk2", "a:srgbClr", "1F497D" }, { "a:lt2", "a:srgbClr", "EEECE1" }, - { "a:accent1", "a:srgbClr", "4F81BD" }, { "a:accent2", "a:srgbClr", "C0504D" }, - { "a:accent3", "a:srgbClr", "9BBB59" }, { "a:accent4", "a:srgbClr", "8064A2" }, - { "a:accent5", "a:srgbClr", "4BACC6" }, { "a:accent6", "a:srgbClr", "F79646" }, - { "a:hlink", "a:srgbClr", "0000FF" }, { "a:folHlink", "a:srgbClr", "800080" }, - }; - - for (auto element : scheme_elements) - { - auto element_node = clr_scheme_node.add_child(element.name); - element_node.add_child(element.sub_element_name).add_attribute("val", element.val); - - if (element.name == "a:dk1") - { - element_node.get_child(element.sub_element_name).add_attribute("lastClr", "000000"); - } - else if (element.name == "a:lt1") - { - element_node.get_child(element.sub_element_name).add_attribute("lastClr", "FFFFFF"); - } - } - - struct font_scheme - { - bool typeface; - std::string script; - std::string major; - std::string minor; - }; - - std::vector font_schemes = { - { true, "a:latin", "Cambria", "Calibri" }, - { true, "a:ea", "", "" }, - { true, "a:cs", "", "" }, - { false, "Jpan", "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf", - "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" }, - { false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95", - "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95" }, - { false, "Hans", "\xe5\xae\x8b\xe4\xbd\x93", "\xe5\xae\x8b\xe4\xbd\x93" }, - { false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94", - "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" }, - { false, "Arab", "Times New Roman", "Arial" }, - { false, "Hebr", "Times New Roman", "Arial" }, - { false, "Thai", "Tahoma", "Tahoma" }, - { false, "Ethi", "Nyala", "Nyala" }, - { false, "Beng", "Vrinda", "Vrinda" }, - { false, "Gujr", "Shruti", "Shruti" }, - { false, "Khmr", "MoolBoran", "DaunPenh" }, - { false, "Knda", "Tunga", "Tunga" }, - { false, "Guru", "Raavi", "Raavi" }, - { false, "Cans", "Euphemia", "Euphemia" }, - { false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee" }, - { false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti" }, - { false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya" }, - { false, "Thaa", "MV Boli", "MV Boli" }, - { false, "Deva", "Mangal", "Mangal" }, - { false, "Telu", "Gautami", "Gautami" }, - { false, "Taml", "Latha", "Latha" }, - { false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa" }, - { false, "Orya", "Kalinga", "Kalinga" }, - { false, "Mlym", "Kartika", "Kartika" }, - { false, "Laoo", "DokChampa", "DokChampa" }, - { false, "Sinh", "Iskoola Pota", "Iskoola Pota" }, - { false, "Mong", "Mongolian Baiti", "Mongolian Baiti" }, - { false, "Viet", "Times New Roman", "Arial" }, - { false, "Uigh", "Microsoft Uighur", "Microsoft Uighur" } - }; - - auto font_scheme_node = theme_elements_node.add_child("a:fontScheme"); - font_scheme_node.add_attribute("name", "Office"); - - auto major_fonts_node = font_scheme_node.add_child("a:majorFont"); - auto minor_fonts_node = font_scheme_node.add_child("a:minorFont"); - - for (auto scheme : font_schemes) - { - if (scheme.typeface) - { - auto major_font_node = major_fonts_node.add_child(scheme.script); - major_font_node.add_attribute("typeface", scheme.major); - - auto minor_font_node = minor_fonts_node.add_child(scheme.script); - minor_font_node.add_attribute("typeface", scheme.minor); - } - else - { - auto major_font_node = major_fonts_node.add_child("a:font"); - major_font_node.add_attribute("script", scheme.script); - major_font_node.add_attribute("typeface", scheme.major); - - auto minor_font_node = minor_fonts_node.add_child("a:font"); - minor_font_node.add_attribute("script", scheme.script); - minor_font_node.add_attribute("typeface", scheme.minor); - } - } - - auto format_scheme_node = theme_elements_node.add_child("a:fmtScheme"); - format_scheme_node.add_attribute("name", "Office"); - - auto fill_style_list_node = format_scheme_node.add_child("a:fillStyleLst"); - fill_style_list_node.add_child("a:solidFill").add_child("a:schemeClr").add_attribute("val", "phClr"); - - auto grad_fill_node = fill_style_list_node.add_child("a:gradFill"); - grad_fill_node.add_attribute("rotWithShape", "1"); - - auto grad_fill_list = grad_fill_node.add_child("a:gsLst"); - auto gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "0"); - auto scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "50000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "300000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "35000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "37000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "300000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "100000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "15000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "350000"); - - auto lin_node = grad_fill_node.add_child("a:lin"); - lin_node.add_attribute("ang", "16200000"); - lin_node.add_attribute("scaled", "1"); - - grad_fill_node = fill_style_list_node.add_child("a:gradFill"); - grad_fill_node.add_attribute("rotWithShape", "1"); - - grad_fill_list = grad_fill_node.add_child("a:gsLst"); - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "0"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "51000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "130000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "80000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "93000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "130000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "100000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "94000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "135000"); - - lin_node = grad_fill_node.add_child("a:lin"); - lin_node.add_attribute("ang", "16200000"); - lin_node.add_attribute("scaled", "0"); - - auto line_style_list_node = format_scheme_node.add_child("a:lnStyleLst"); - - auto ln_node = line_style_list_node.add_child("a:ln"); - ln_node.add_attribute("w", "9525"); - ln_node.add_attribute("cap", "flat"); - ln_node.add_attribute("cmpd", "sng"); - ln_node.add_attribute("algn", "ctr"); - - auto solid_fill_node = ln_node.add_child("a:solidFill"); - scheme_color_node = solid_fill_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "95000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "105000"); - ln_node.add_child("a:prstDash").add_attribute("val", "solid"); - - ln_node = line_style_list_node.add_child("a:ln"); - ln_node.add_attribute("w", "25400"); - ln_node.add_attribute("cap", "flat"); - ln_node.add_attribute("cmpd", "sng"); - ln_node.add_attribute("algn", "ctr"); - - solid_fill_node = ln_node.add_child("a:solidFill"); - scheme_color_node = solid_fill_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - ln_node.add_child("a:prstDash").add_attribute("val", "solid"); - - ln_node = line_style_list_node.add_child("a:ln"); - ln_node.add_attribute("w", "38100"); - ln_node.add_attribute("cap", "flat"); - ln_node.add_attribute("cmpd", "sng"); - ln_node.add_attribute("algn", "ctr"); - - solid_fill_node = ln_node.add_child("a:solidFill"); - scheme_color_node = solid_fill_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - ln_node.add_child("a:prstDash").add_attribute("val", "solid"); - - auto effect_style_list_node = format_scheme_node.add_child("a:effectStyleLst"); - auto effect_style_node = effect_style_list_node.add_child("a:effectStyle"); - auto effect_list_node = effect_style_node.add_child("a:effectLst"); - auto outer_shadow_node = effect_list_node.add_child("a:outerShdw"); - outer_shadow_node.add_attribute("blurRad", "40000"); - outer_shadow_node.add_attribute("dist", "20000"); - outer_shadow_node.add_attribute("dir", "5400000"); - outer_shadow_node.add_attribute("rotWithShape", "0"); - auto srgb_clr_node = outer_shadow_node.add_child("a:srgbClr"); - srgb_clr_node.add_attribute("val", "000000"); - srgb_clr_node.add_child("a:alpha").add_attribute("val", "38000"); - - effect_style_node = effect_style_list_node.add_child("a:effectStyle"); - effect_list_node = effect_style_node.add_child("a:effectLst"); - outer_shadow_node = effect_list_node.add_child("a:outerShdw"); - outer_shadow_node.add_attribute("blurRad", "40000"); - outer_shadow_node.add_attribute("dist", "23000"); - outer_shadow_node.add_attribute("dir", "5400000"); - outer_shadow_node.add_attribute("rotWithShape", "0"); - srgb_clr_node = outer_shadow_node.add_child("a:srgbClr"); - srgb_clr_node.add_attribute("val", "000000"); - srgb_clr_node.add_child("a:alpha").add_attribute("val", "35000"); - - effect_style_node = effect_style_list_node.add_child("a:effectStyle"); - effect_list_node = effect_style_node.add_child("a:effectLst"); - outer_shadow_node = effect_list_node.add_child("a:outerShdw"); - outer_shadow_node.add_attribute("blurRad", "40000"); - outer_shadow_node.add_attribute("dist", "23000"); - outer_shadow_node.add_attribute("dir", "5400000"); - outer_shadow_node.add_attribute("rotWithShape", "0"); - srgb_clr_node = outer_shadow_node.add_child("a:srgbClr"); - srgb_clr_node.add_attribute("val", "000000"); - srgb_clr_node.add_child("a:alpha").add_attribute("val", "35000"); - auto scene3d_node = effect_style_node.add_child("a:scene3d"); - auto camera_node = scene3d_node.add_child("a:camera"); - camera_node.add_attribute("prst", "orthographicFront"); - auto rot_node = camera_node.add_child("a:rot"); - rot_node.add_attribute("lat", "0"); - rot_node.add_attribute("lon", "0"); - rot_node.add_attribute("rev", "0"); - auto light_rig_node = scene3d_node.add_child("a:lightRig"); - light_rig_node.add_attribute("rig", "threePt"); - light_rig_node.add_attribute("dir", "t"); - rot_node = light_rig_node.add_child("a:rot"); - rot_node.add_attribute("lat", "0"); - rot_node.add_attribute("lon", "0"); - rot_node.add_attribute("rev", "1200000"); - - auto bevel_node = effect_style_node.add_child("a:sp3d").add_child("a:bevelT"); - bevel_node.add_attribute("w", "63500"); - bevel_node.add_attribute("h", "25400"); - - auto bg_fill_style_list_node = format_scheme_node.add_child("a:bgFillStyleLst"); - - bg_fill_style_list_node.add_child("a:solidFill").add_child("a:schemeClr").add_attribute("val", "phClr"); - - grad_fill_node = bg_fill_style_list_node.add_child("a:gradFill"); - grad_fill_node.add_attribute("rotWithShape", "1"); - - grad_fill_list = grad_fill_node.add_child("a:gsLst"); - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "0"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "40000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "350000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "40000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "45000"); - scheme_color_node.add_child("a:shade").add_attribute("val", "99000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "350000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "100000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "20000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "255000"); - - auto path_node = grad_fill_node.add_child("a:path"); - path_node.add_attribute("path", "circle"); - auto fill_to_rect_node = path_node.add_child("a:fillToRect"); - fill_to_rect_node.add_attribute("l", "50000"); - fill_to_rect_node.add_attribute("t", "-80000"); - fill_to_rect_node.add_attribute("r", "50000"); - fill_to_rect_node.add_attribute("b", "180000"); - - grad_fill_node = bg_fill_style_list_node.add_child("a:gradFill"); - grad_fill_node.add_attribute("rotWithShape", "1"); - - grad_fill_list = grad_fill_node.add_child("a:gsLst"); - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "0"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:tint").add_attribute("val", "80000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "300000"); - - gs_node = grad_fill_list.add_child("a:gs"); - gs_node.add_attribute("pos", "100000"); - scheme_color_node = gs_node.add_child("a:schemeClr"); - scheme_color_node.add_attribute("val", "phClr"); - scheme_color_node.add_child("a:shade").add_attribute("val", "30000"); - scheme_color_node.add_child("a:satMod").add_attribute("val", "200000"); - - path_node = grad_fill_node.add_child("a:path"); - path_node.add_attribute("path", "circle"); - fill_to_rect_node = path_node.add_child("a:fillToRect"); - fill_to_rect_node.add_attribute("l", "50000"); - fill_to_rect_node.add_attribute("t", "50000"); - fill_to_rect_node.add_attribute("r", "50000"); - fill_to_rect_node.add_attribute("b", "50000"); - - theme_node.add_child("a:objectDefaults"); - theme_node.add_child("a:extraClrSchemeLst"); - - return xml; -} - -} // namespace xlnt diff --git a/source/serialization/workbook_serializer.cpp b/source/serialization/workbook_serializer.cpp deleted file mode 100644 index 2b78e276..00000000 --- a/source/serialization/workbook_serializer.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// Copyright (c) 2010-2015 openpyxl -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace { - -xlnt::datetime w3cdtf_to_datetime(const std::string &string) -{ - xlnt::datetime result(1900, 1, 1); - auto separator_index = string.find('-'); - result.year = std::stoi(string.substr(0, separator_index)); - result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1))); - separator_index = string.find('-', separator_index + 1); - result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1))); - separator_index = string.find('T', separator_index + 1); - result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); - separator_index = string.find(':', separator_index + 1); - result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); - separator_index = string.find(':', separator_index + 1); - result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1))); - return result; -} - -std::string fill(const std::string &string, std::size_t length = 2) -{ - if (string.size() >= length) - { - return string; - } - - return std::string(length - string.size(), '0') + string; -} - -std::string datetime_to_w3cdtf(const xlnt::datetime &dt) -{ - return std::to_string(dt.year) + "-" + fill(std::to_string(dt.month)) + "-" + fill(std::to_string(dt.day)) + "T" + - fill(std::to_string(dt.hour)) + ":" + fill(std::to_string(dt.minute)) + ":" + - fill(std::to_string(dt.second)) + "Z"; -} - -} // namespace - -namespace xlnt { - -workbook_serializer::workbook_serializer(workbook &wb) : workbook_(wb) -{ -} - -void workbook_serializer::read_properties_core(const xml_document &xml) -{ - auto &props = workbook_.get_properties(); - auto root_node = xml.get_child("cp:coreProperties"); - - props.excel_base_date = calendar::windows_1900; - - if (root_node.has_child("dc:creator")) - { - props.creator = root_node.get_child("dc:creator").get_text(); - } - - if (root_node.has_child("cp:lastModifiedBy")) - { - props.last_modified_by = root_node.get_child("cp:lastModifiedBy").get_text(); - } - - if (root_node.has_child("dcterms:created")) - { - std::string created_string = root_node.get_child("dcterms:created").get_text(); - props.created = w3cdtf_to_datetime(created_string); - } - - if (root_node.has_child("dcterms:modified")) - { - std::string modified_string = root_node.get_child("dcterms:modified").get_text(); - props.modified = w3cdtf_to_datetime(modified_string); - } -} - -void workbook_serializer::read_properties_app(const xml_document &xml) -{ - auto &props = workbook_.get_app_properties(); - auto root_node = xml.get_child("Properties"); - - if(root_node.has_child("Application")) - { - props.application = root_node.get_child("Application").get_text(); - } - - if(root_node.has_child("DocSecurity")) - { - props.doc_security = std::stoi(root_node.get_child("DocSecurity").get_text()); - } - - if(root_node.has_child("ScaleCrop")) - { - props.scale_crop = root_node.get_child("ScaleCrop").get_text() == "true"; - } - - if(root_node.has_child("Company")) - { - props.company = root_node.get_child("Company").get_text(); - } - - if(root_node.has_child("ScaleCrop")) - { - props.links_up_to_date = root_node.get_child("ScaleCrop").get_text() == "true"; - } - - if(root_node.has_child("SharedDoc")) - { - props.shared_doc = root_node.get_child("SharedDoc").get_text() == "true"; - } - - if(root_node.has_child("HyperlinksChanged")) - { - props.hyperlinks_changed = root_node.get_child("HyperlinksChanged").get_text() == "true"; - } - - if(root_node.has_child("AppVersion")) - { - props.app_version = root_node.get_child("AppVersion").get_text(); - } -} - -xml_document workbook_serializer::write_properties_core() const -{ - auto &props = workbook_.get_properties(); - - xml_document xml; - - auto root_node = xml.add_child("cp:coreProperties"); - - xml.add_namespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); - xml.add_namespace("dc", "http://purl.org/dc/elements/1.1/"); - xml.add_namespace("dcmitype", "http://purl.org/dc/dcmitype/"); - xml.add_namespace("dcterms", "http://purl.org/dc/terms/"); - xml.add_namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); - - root_node.add_child("dc:creator").set_text(props.creator); - root_node.add_child("cp:lastModifiedBy").set_text(props.last_modified_by); - root_node.add_child("dcterms:created").set_text(datetime_to_w3cdtf(props.created)); - root_node.get_child("dcterms:created").add_attribute("xsi:type", "dcterms:W3CDTF"); - root_node.add_child("dcterms:modified").set_text(datetime_to_w3cdtf(props.modified)); - root_node.get_child("dcterms:modified").add_attribute("xsi:type", "dcterms:W3CDTF"); - root_node.add_child("dc:title").set_text(props.title); - root_node.add_child("dc:description"); - root_node.add_child("dc:subject"); - root_node.add_child("cp:keywords"); - root_node.add_child("cp:category"); - - return xml; -} - -xml_document workbook_serializer::write_properties_app() const -{ - xml_document xml; - - auto root_node = xml.add_child("Properties"); - - xml.add_namespace("", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); - xml.add_namespace("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); - - auto &properties = workbook_.get_app_properties(); - - root_node.add_child("Application").set_text(properties.application); - root_node.add_child("DocSecurity").set_text(std::to_string(properties.doc_security)); - root_node.add_child("ScaleCrop").set_text(properties.scale_crop ? "true" : "false"); - - auto company_node = root_node.add_child("Company"); - - if (!properties.company.empty()) - { - company_node.set_text(properties.company); - } - - root_node.add_child("LinksUpToDate").set_text(properties.links_up_to_date ? "true" : "false"); - root_node.add_child("SharedDoc").set_text(properties.shared_doc ? "true" : "false"); - root_node.add_child("HyperlinksChanged").set_text(properties.hyperlinks_changed ? "true" : "false"); - root_node.add_child("AppVersion").set_text(properties.app_version); - - // TODO what is this stuff? - - auto heading_pairs_node = root_node.add_child("HeadingPairs"); - auto heading_pairs_vector_node = heading_pairs_node.add_child("vt:vector"); - heading_pairs_vector_node.add_attribute("size", "2"); - heading_pairs_vector_node.add_attribute("baseType", "variant"); - heading_pairs_vector_node.add_child("vt:variant").add_child("vt:lpstr").set_text("Worksheets"); - heading_pairs_vector_node.add_child("vt:variant") - .add_child("vt:i4") - .set_text(std::to_string(workbook_.get_sheet_names().size())); - - auto titles_of_parts_node = root_node.add_child("TitlesOfParts"); - auto titles_of_parts_vector_node = titles_of_parts_node.add_child("vt:vector"); - titles_of_parts_vector_node.add_attribute("size", std::to_string(workbook_.get_sheet_names().size())); - titles_of_parts_vector_node.add_attribute("baseType", "lpstr"); - - for (auto ws : workbook_) - { - titles_of_parts_vector_node.add_child("vt:lpstr").set_text(ws.get_title()); - } - - return xml; -} - -xml_document workbook_serializer::write_workbook() const -{ - std::size_t num_visible = 0; - - for (auto ws : workbook_) - { - if (ws.get_page_setup().get_sheet_state() == sheet_state::visible) - { - num_visible++; - } - } - - if (num_visible == 0) - { - throw xlnt::value_error(); - } - - xml_document xml; - - auto root_node = xml.add_child("workbook"); - - xml.add_namespace("", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - xml.add_namespace("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); - - auto file_version_node = root_node.add_child("fileVersion"); - file_version_node.add_attribute("appName", "xl"); - file_version_node.add_attribute("lastEdited", "4"); - file_version_node.add_attribute("lowestEdited", "4"); - file_version_node.add_attribute("rupBuild", "4505"); - - auto workbook_pr_node = root_node.add_child("workbookPr"); - workbook_pr_node.add_attribute("codeName", "ThisWorkbook"); - workbook_pr_node.add_attribute("defaultThemeVersion", "124226"); - workbook_pr_node.add_attribute("date1904", - workbook_.get_properties().excel_base_date == calendar::mac_1904 ? "1" : "0"); - - auto book_views_node = root_node.add_child("bookViews"); - auto workbook_view_node = book_views_node.add_child("workbookView"); - workbook_view_node.add_attribute("activeTab", "0"); - workbook_view_node.add_attribute("autoFilterDateGrouping", "1"); - workbook_view_node.add_attribute("firstSheet", "0"); - workbook_view_node.add_attribute("minimized", "0"); - workbook_view_node.add_attribute("showHorizontalScroll", "1"); - workbook_view_node.add_attribute("showSheetTabs", "1"); - workbook_view_node.add_attribute("showVerticalScroll", "1"); - workbook_view_node.add_attribute("tabRatio", "600"); - workbook_view_node.add_attribute("visibility", "visible"); - - auto sheets_node = root_node.add_child("sheets"); - auto defined_names_node = root_node.add_child("definedNames"); - - for (const auto &relationship : workbook_.get_relationships()) - { - if (relationship.get_type() == relationship::type::worksheet) - { - // TODO: this is ugly - std::string sheet_index_string = relationship.get_target_uri(); - sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.')); - sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/')); - auto iter = sheet_index_string.end(); - iter--; - while (isdigit(*iter)) - iter--; - auto first_digit = iter - sheet_index_string.begin(); - sheet_index_string = sheet_index_string.substr(static_cast(first_digit + 1)); - std::size_t sheet_index = static_cast(std::stoll(sheet_index_string) - 1); - - auto ws = workbook_.get_sheet_by_index(sheet_index); - - auto sheet_node = sheets_node.add_child("sheet"); - sheet_node.add_attribute("name", ws.get_title()); - sheet_node.add_attribute("sheetId", std::to_string(sheet_index + 1)); - sheet_node.add_attribute("r:id", relationship.get_id()); - - if (ws.has_auto_filter()) - { - auto defined_name_node = defined_names_node.add_child("definedName"); - defined_name_node.add_attribute("name", "_xlnm._FilterDatabase"); - defined_name_node.add_attribute("hidden", "1"); - defined_name_node.add_attribute("localSheetId", "0"); - std::string name = - "'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string(); - defined_name_node.set_text(name); - } - } - } - - auto calc_pr_node = root_node.add_child("calcPr"); - calc_pr_node.add_attribute("calcId", "124519"); - calc_pr_node.add_attribute("calcMode", "auto"); - calc_pr_node.add_attribute("fullCalcOnLoad", "1"); - - return xml; -} - -xml_node workbook_serializer::write_named_ranges() const -{ - xlnt::xml_node named_ranges_node; - - for (auto &named_range : workbook_.get_named_ranges()) - { - named_ranges_node.add_child(named_range.get_name()); - } - - return named_ranges_node; -} - -} // namespace xlnt diff --git a/source/serialization/xml_document.cpp b/source/serialization/xml_document.cpp deleted file mode 100644 index 8cafa10a..00000000 --- a/source/serialization/xml_document.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#include -#include -#include - -#include -#include -#include - -namespace xlnt { - -xml_document::xml_document() : d_(new detail::xml_document_impl()) -{ -} - -xml_document::xml_document(const xml_document &other) : xml_document() -{ - d_->doc.append_copy(other.d_->doc.root()); -} - -xml_document::xml_document(xml_document &&other) -{ - std::swap(d_, other.d_); -} - -xml_document::~xml_document() -{ -} - -void xml_document::set_encoding(const std::string &encoding) -{ - d_->encoding = encoding; -} - -void xml_document::add_namespace(const std::string &id, const std::string &uri) -{ - d_->doc.first_child().append_attribute((id.empty() ? "xmlns" : "xmlns:" + id).c_str()).set_value(uri.c_str()); -} - -xml_node xml_document::add_child(const xml_node &child) -{ - auto child_node = d_->doc.root().append_copy(child.d_->node); - return xml_node(detail::xml_node_impl(child_node)); -} - -xml_node xml_document::add_child(const std::string &child_name) -{ - auto child = d_->doc.root().append_child(child_name.c_str()); - return xml_node(detail::xml_node_impl(child)); -} - -xml_node xml_document::get_root() -{ - return xml_node(detail::xml_node_impl(d_->doc.root())); -} - -const xml_node xml_document::get_root() const -{ - return xml_node(detail::xml_node_impl(d_->doc.root())); -} - -std::string xml_document::to_string() const -{ - return xml_serializer::serialize(*this); -} - -xml_document &xml_document::from_string(const std::string &xml_string) -{ - d_->doc.load(xml_string.c_str()); - - return *this; -} - -xml_node xml_document::get_child(const std::string &child_name) -{ - return xml_node(detail::xml_node_impl(d_->doc.child(child_name.c_str()))); -} - -const xml_node xml_document::get_child(const std::string &child_name) const -{ - return xml_node(detail::xml_node_impl(d_->doc.child(child_name.c_str()))); -} - -} // namespace xlnt diff --git a/source/serialization/xml_node.cpp b/source/serialization/xml_node.cpp deleted file mode 100644 index 12b1630d..00000000 --- a/source/serialization/xml_node.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#include -#include - -#include - -namespace xlnt { - -xml_node::xml_node() : d_(new detail::xml_node_impl) -{ -} - -xml_node::xml_node(const detail::xml_node_impl &d) : xml_node() -{ - d_->node = d.node; -} - -xml_node::~xml_node() -{ -} - -xml_node::xml_node(const xml_node &other) : xml_node() -{ - d_->node = other.d_->node; -} - -xml_node &xml_node::operator=(const xlnt::xml_node &other) -{ - d_->node = other.d_->node; - - return *this; -} - -std::string xml_node::get_name() const -{ - return d_->node.name(); -} - -void xml_node::set_name(const std::string &name) -{ - d_->node.set_name(name.c_str()); -} - -bool xml_node::has_text() const -{ - return d_->node.text() != nullptr; -} - -std::string xml_node::get_text() const -{ - return d_->node.text().as_string(); -} - -void xml_node::set_text(const std::string &text) -{ - d_->node.text().set(text.c_str()); -} - -const std::vector xml_node::get_children() const -{ - std::vector children; - - for (auto child : d_->node.children()) - { - children.push_back(xml_node(detail::xml_node_impl(child))); - } - - return children; -} - -xml_node xml_node::add_child(const xml_node &child) -{ - auto child_node = xml_node(detail::xml_node_impl(d_->node.append_child(child.get_name().c_str()))); - - for (auto attr : child.get_attributes()) - { - child_node.add_attribute(attr.first, attr.second); - } - - for (auto child_child : child.get_children()) - { - child_node.add_child(child_child); - } - - return child_node; -} - -xml_node xml_node::add_child(const std::string &child_name) -{ - return xml_node(detail::xml_node_impl(d_->node.append_child(child_name.c_str()))); -} - -const std::vector xml_node::get_attributes() const -{ - std::vector attributes; - - for (auto attr : d_->node.attributes()) - { - attributes.push_back(std::make_pair(attr.name(), attr.value())); - } - - return attributes; -} - -void xml_node::add_attribute(const std::string &name, const std::string &value) -{ - d_->node.append_attribute(name.c_str()).set_value(value.c_str()); -} - -bool xml_node::has_attribute(const std::string &attribute_name) const -{ - return d_->node.attribute(attribute_name.c_str()) != nullptr; -} - -std::string xml_node::get_attribute(const std::string &attribute_name) const -{ - return d_->node.attribute(attribute_name.c_str()).value(); -} - -bool xml_node::has_child(const std::string &child_name) const -{ - return d_->node.child(child_name.c_str()) != nullptr; -} - -xml_node xml_node::get_child(const std::string &child_name) -{ - return xml_node(detail::xml_node_impl(d_->node.child(child_name.c_str()))); -} - -const xml_node xml_node::get_child(const std::string &child_name) const -{ - return xml_node(detail::xml_node_impl(d_->node.child(child_name.c_str()))); -} - -std::string xml_node::to_string() const -{ - return xml_serializer::serialize_node(*this); -} - -} // namespace xlnt diff --git a/source/serialization/xml_serializer.cpp b/source/serialization/xml_serializer.cpp deleted file mode 100644 index 256e0bd0..00000000 --- a/source/serialization/xml_serializer.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#include - -#include -#include -#include - -#include "detail/include_pugixml.hpp" -#include "detail/xml_document_impl.hpp" -#include "detail/xml_node_impl.hpp" - -namespace xlnt { - -std::string xml_serializer::serialize(const xml_document &xml) -{ - std::ostringstream ss; - xml.d_->doc.save(ss, " ", pugi::format_default, pugi::encoding_utf8); - - return ss.str(); -} - -xml_document xml_serializer::deserialize(const std::string &xml_string) -{ - xml_document doc; - doc.d_->doc.load(xml_string.c_str()); - - return doc; -} - -std::string xml_serializer::serialize_node(const xml_node &xml) -{ - pugi::xml_document doc; - doc.append_copy(xml.d_->node); - - std::ostringstream ss; - doc.save(ss); - - return ss.str(); -} - -} // namespace xlnt diff --git a/source/styles/tests/test_stylesheet.hpp b/source/styles/tests/test_stylesheet.hpp index 6a87f6a1..a154de70 100644 --- a/source/styles/tests/test_stylesheet.hpp +++ b/source/styles/tests/test_stylesheet.hpp @@ -1,9 +1,11 @@ #pragma once #include +#include #include -#include "pugixml.hpp" +#include +#include #include #include #include @@ -18,9 +20,11 @@ public: xlnt::excel_serializer excel_serializer(wb); xlnt::style_serializer style_serializer(excel_serializer.get_stylesheet()); xlnt::zip_file archive; - xlnt::xml_document stylesheet_doc; + pugi::xml_document stylesheet_doc; style_serializer.write_stylesheet(stylesheet_doc); - auto stylesheet_xml = stylesheet_doc.to_string(); + std::ostringstream ss; + stylesheet_doc.save(ss); + auto stylesheet_xml = ss.str(); const std::string expected = "" @@ -71,9 +75,9 @@ public: void test_from_simple() { - xlnt::xml_document doc; + pugi::xml_document doc; auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/simple-styles.xml")); - doc.from_string(xml); + doc.load(xml.c_str()); xlnt::workbook wb; xlnt::excel_serializer e(wb); xlnt::style_serializer s(e.get_stylesheet()); @@ -83,9 +87,9 @@ public: void test_from_complex() { - xlnt::xml_document doc; + pugi::xml_document doc; auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/complex-styles.xml")); - doc.from_string(xml); + doc.load(xml.c_str()); xlnt::workbook wb; xlnt::excel_serializer e(wb); xlnt::style_serializer s(e.get_stylesheet()); diff --git a/source/serialization/tests/test_read.hpp b/source/workbook/tests/test_read.hpp similarity index 98% rename from source/serialization/tests/test_read.hpp rename to source/workbook/tests/test_read.hpp index 26eedc5f..7e20f98e 100644 --- a/source/serialization/tests/test_read.hpp +++ b/source/workbook/tests/test_read.hpp @@ -2,20 +2,16 @@ #include #include - #include -#include -#include -#include -#include -#include -#include - +#include +#include +#include +#include #include - #include #include +#include class test_read : public CxxTest::TestSuite { diff --git a/source/serialization/tests/test_style_writer.hpp b/source/workbook/tests/test_style_writer.hpp similarity index 96% rename from source/serialization/tests/test_style_writer.hpp rename to source/workbook/tests/test_style_writer.hpp index 4ef8aa66..0f52ada9 100644 --- a/source/serialization/tests/test_style_writer.hpp +++ b/source/workbook/tests/test_style_writer.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -16,15 +16,15 @@ public: wb.get_active_sheet().get_cell("A1").set_number_format(xlnt::number_format("YYYY")); xlnt::excel_serializer excel_serializer(wb); xlnt::style_serializer style_serializer(excel_serializer.get_stylesheet()); - xlnt::xml_document observed; + pugi::xml_document observed; style_serializer.write_stylesheet(observed); - xlnt::xml_document expected_doc; + pugi::xml_document expected_doc; std::string expected = " " " " " "; - expected_doc.from_string(expected); - auto diff = Helper::compare_xml(expected_doc.get_child("numFmts"), observed.get_child("styleSheet").get_child("numFmts")); + expected_doc.load(expected.c_str()); + auto diff = Helper::compare_xml(expected_doc.child("numFmts"), observed.child("styleSheet").child("numFmts")); TS_ASSERT(diff); } /* diff --git a/source/workbook/tests/test_theme.hpp b/source/workbook/tests/test_theme.hpp index 2c70127b..6cd1cb3b 100644 --- a/source/workbook/tests/test_theme.hpp +++ b/source/workbook/tests/test_theme.hpp @@ -3,12 +3,11 @@ #include #include -#include +#include +#include +#include #include -#include "helpers/path_helper.hpp" -#include "helpers/helper.hpp" - class test_theme : public CxxTest::TestSuite { public: @@ -16,7 +15,8 @@ public: { xlnt::workbook wb; xlnt::theme_serializer serializer; - auto xml = serializer.write_theme(wb.get_loaded_theme()); + pugi::xml_document xml; + serializer.write_theme(wb.get_loaded_theme(), xml); TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", xml)); } }; diff --git a/source/serialization/tests/test_write.hpp b/source/workbook/tests/test_write.hpp similarity index 73% rename from source/serialization/tests/test_write.hpp rename to source/workbook/tests/test_write.hpp index cd78727b..51c357a7 100644 --- a/source/serialization/tests/test_write.hpp +++ b/source/workbook/tests/test_write.hpp @@ -3,16 +3,15 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include -#include "helpers/temporary_file.hpp" -#include "helpers/path_helper.hpp" -#include "helpers/helper.hpp" - class test_write : public CxxTest::TestSuite { public: @@ -50,18 +49,20 @@ public: xlnt::zip_file archive; xlnt::relationship_serializer serializer(archive); serializer.write_relationships(wb.get_relationships(), "xl/workbook.xml"); - auto content = xlnt::xml_serializer::deserialize(archive.read("xl/_rels/workbook.xml.rels")); + pugi::xml_document xml; + xml.load(archive.read("xl/_rels/workbook.xml.rels").c_str()); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", content)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml.rels", xml)); } void test_write_workbook() { xlnt::workbook wb; xlnt::workbook_serializer serializer(wb); - auto content = serializer.write_workbook(); + pugi::xml_document xml; + serializer.write_workbook(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", content)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook.xml", xml)); } void test_write_string_table() @@ -73,9 +74,10 @@ public: ws.get_cell("A2").set_value("world"); ws.get_cell("A3").set_value("nice"); - auto content = xlnt::shared_strings_serializer::write_shared_strings(wb.get_shared_strings()); + pugi::xml_document xml; + xlnt::shared_strings_serializer::write_shared_strings(wb.get_shared_strings(), xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", content)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", xml)); } void test_write_worksheet() @@ -84,9 +86,10 @@ public: ws.get_cell("F42").set_value("hello"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", xml)); } void test_write_hidden_worksheet() @@ -96,9 +99,10 @@ public: ws.get_cell("F42").set_value("hello"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1.xml", xml)); } void test_write_bool() @@ -108,9 +112,10 @@ public: ws.get_cell("F43").set_value(true); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_bool.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_bool.xml", xml)); } void test_write_formula() @@ -121,9 +126,10 @@ public: ws.get_cell("F3").set_formula("F1+F2"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_formula.xml", xml)); } void test_write_height() @@ -133,9 +139,10 @@ public: ws.get_row_properties(ws.get_cell("F1").get_row()).height = 30; xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_height.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_height.xml", xml)); } void test_write_hyperlink() @@ -147,9 +154,10 @@ public: ws.get_cell("A1").set_hyperlink("http://test.com"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml", xml)); } void test_write_hyperlink_rels() @@ -166,9 +174,10 @@ public: xlnt::zip_file archive; xlnt::relationship_serializer serializer(archive); serializer.write_relationships(ws.get_relationships(), "xl/worksheets/sheet1.xml"); - auto content = xlnt::xml_serializer::deserialize(archive.read("xl/worksheets/_rels/sheet1.xml.rels")); + pugi::xml_document xml; + xml.load(archive.read("xl/worksheets/_rels/sheet1.xml.rels").c_str()); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml.rels", content)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_hyperlink.xml.rels", xml)); } void _test_write_hyperlink_image_rels() @@ -193,14 +202,16 @@ public: ws.auto_filter("A1:F1"); xlnt::worksheet_serializer ws_serializer(ws); - auto observed = ws_serializer.write_worksheet(); + pugi::xml_document xml; + ws_serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_auto_filter.xml", xml)); xlnt::workbook_serializer wb_serializer(wb); - auto observed2 = wb_serializer.write_workbook(); + pugi::xml_document xml2; + wb_serializer.write_workbook(xml2); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", observed2)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/workbook_auto_filter.xml", xml2)); } void test_write_auto_filter_filter_column() @@ -220,9 +231,10 @@ public: ws.freeze_panes("A4"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); - auto temp = observed.to_string(); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", observed)); + pugi::xml_document xml; + serializer.write_worksheet(xml); + + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", xml)); } void test_freeze_panes_vert() @@ -232,9 +244,10 @@ public: ws.freeze_panes("D1"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_vert.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_vert.xml", xml)); } void test_freeze_panes_both() @@ -244,9 +257,10 @@ public: ws.freeze_panes("D4"); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_both.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_both.xml", xml)); } void test_long_number() @@ -255,9 +269,10 @@ public: ws.get_cell("A1").set_value(9781231231230LL); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/long_number.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/long_number.xml", xml)); } void test_short_number() @@ -266,9 +281,10 @@ public: ws.get_cell("A1").set_value(1234567890); xlnt::worksheet_serializer serializer(ws); - auto observed = serializer.write_worksheet(); + pugi::xml_document xml; + serializer.write_worksheet(xml); - TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/short_number.xml", observed)); + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/short_number.xml", xml)); } void _test_write_images() diff --git a/source/serialization/tests/test_write_workbook.hpp b/source/workbook/tests/test_write_workbook.hpp similarity index 84% rename from source/serialization/tests/test_write_workbook.hpp rename to source/workbook/tests/test_write_workbook.hpp index f4dade69..78ad6fb7 100644 --- a/source/serialization/tests/test_write_workbook.hpp +++ b/source/workbook/tests/test_write_workbook.hpp @@ -3,10 +3,9 @@ #include #include -#include -#include - +#include #include +#include class test_write_workbook : public CxxTest::TestSuite { @@ -19,9 +18,10 @@ public: ws.auto_filter("A1:F1"); xlnt::workbook_serializer serializer(wb); - auto observed = serializer.write_workbook(); + pugi::xml_document xml; + serializer.write_workbook(xml); - auto diff = Helper::compare_xml(PathHelper::read_file("workbook_auto_filter.xml"), observed); + auto diff = Helper::compare_xml(PathHelper::read_file("workbook_auto_filter.xml"), xml); TS_ASSERT(!diff); } @@ -33,7 +33,8 @@ public: wb.create_sheet(); xlnt::workbook_serializer serializer(wb); - auto observed = serializer.write_workbook(); + pugi::xml_document xml; + serializer.write_workbook(xml); std::string expected_string = "" @@ -49,10 +50,10 @@ public: " " ""; - xlnt::xml_document expected; - expected.from_string(expected_string); + pugi::xml_document expected; + expected.load(expected_string.c_str()); - auto diff = Helper::compare_xml(expected, observed); + auto diff = Helper::compare_xml(expected, xml); TS_ASSERT(!diff); } @@ -64,7 +65,8 @@ public: xlnt::workbook_serializer serializer(wb); - TS_ASSERT_THROWS(serializer.write_workbook(), xlnt::value_error); + pugi::xml_document xml; + TS_ASSERT_THROWS(serializer.write_workbook(xml), xlnt::value_error); } void test_write_empty_workbook() @@ -98,8 +100,8 @@ public: xlnt::zip_file archive; xlnt::relationship_serializer serializer(archive); serializer.write_relationships(wb.get_relationships(), "xl/workbook.xml"); - xlnt::xml_document observed; - observed.from_string(archive.read("xl/_rels/workbook.xml.rels")); + pugi::xml_document observed; + observed.load(archive.read("xl/_rels/workbook.xml.rels").c_str()); auto filename = "workbook.xml.rels"; auto diff = Helper::compare_xml(PathHelper::read_file(filename), observed); TS_ASSERT(!diff); @@ -109,9 +111,10 @@ public: { xlnt::workbook wb; xlnt::workbook_serializer serializer(wb); - auto observed = serializer.write_workbook(); + pugi::xml_document xml; + serializer.write_workbook(xml); auto filename = PathHelper::GetDataDirectory("/workbook.xml"); - auto diff = Helper::compare_xml(PathHelper::read_file(filename), observed); + auto diff = Helper::compare_xml(PathHelper::read_file(filename), xml); TS_ASSERT(!diff); } @@ -121,14 +124,13 @@ public: auto ws = wb.create_sheet(); wb.create_named_range("test_range", ws, "A1:B5"); xlnt::workbook_serializer serializer(wb); - auto observed_node = serializer.write_named_ranges(); - xlnt::xml_document observed; - observed.add_child(observed_node); + pugi::xml_document xml; + serializer.write_named_ranges(xml.root()); std::string expected = "" "'Sheet'!$A$1:$B$5" ""; - auto diff = Helper::compare_xml(expected, observed); + auto diff = Helper::compare_xml(expected, xml); TS_ASSERT(!diff); } @@ -144,7 +146,8 @@ public: wb.set_code_name("MyWB"); xlnt::workbook_serializer serializer(wb); - auto observed = serializer.write_workbook(); + pugi::xml_document xml; + serializer.write_workbook(xml); std::string expected = "" @@ -158,7 +161,7 @@ public: " " " " ""; - auto diff = Helper::compare_xml(expected, observed); + auto diff = Helper::compare_xml(expected, xml); TS_ASSERT(!diff); } @@ -168,8 +171,8 @@ public: xlnt::zip_file archive; xlnt::relationship_serializer serializer(archive); serializer.write_relationships(wb.get_root_relationships(), ""); - xlnt::xml_document observed; - observed.from_string(archive.read("_rels/.rels")); + pugi::xml_document observed; + observed.load(archive.read("_rels/.rels").c_str()); std::string expected = "" @@ -179,7 +182,7 @@ public: ""; auto diff = Helper::compare_xml(expected, observed); - TS_ASSERT(!diff); + TS_ASSERT(diff); } private: diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 4f8267b6..5f09a534 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include #include #include @@ -45,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +52,7 @@ #include #include +#include #include #include #include diff --git a/source/worksheet/tests/test_worksheet.hpp b/source/worksheet/tests/test_worksheet.hpp index 191ae671..c5b7907a 100644 --- a/source/worksheet/tests/test_worksheet.hpp +++ b/source/worksheet/tests/test_worksheet.hpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include diff --git a/tests/helpers/helper.hpp b/tests/helpers/helper.hpp index 82792b7b..351d501e 100644 --- a/tests/helpers/helper.hpp +++ b/tests/helpers/helper.hpp @@ -1,11 +1,8 @@ #pragma once +#include #include -#include -#include -#include - #include "path_helper.hpp" class Helper @@ -31,12 +28,12 @@ public: operator bool() const { return difference == difference_type::equivalent; } }; - static comparison_result compare_xml(const xlnt::xml_document &expected, const xlnt::xml_document &observed) + static comparison_result compare_xml(const pugi::xml_document &expected, const pugi::xml_document &observed) { - return compare_xml(expected.get_root(), observed.get_root()); + return compare_xml(expected.root(), observed.root()); } - - static comparison_result compare_xml(const std::string &expected, const xlnt::xml_document &observed) + + static comparison_result compare_xml(const std::string &expected, const pugi::xml_document &observed) { std::string expected_contents = expected; @@ -49,46 +46,48 @@ public: expected_contents = s.str(); } - xlnt::xml_document expected_xml; - expected_xml.from_string(expected_contents); + pugi::xml_document expected_xml; + expected_xml.load(expected_contents.c_str()); - auto observed_string = observed.to_string(); + std::ostringstream ss; + observed.save(ss); + auto observed_string = ss.str(); - return compare_xml(expected_xml.get_root(), observed.get_root()); + return compare_xml(expected_xml.root(), observed.root()); } static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents) { - xlnt::xml_document left_xml; - left_xml.from_string(left_contents); + pugi::xml_document left_xml; + left_xml.load(left_contents.c_str()); - xlnt::xml_document right_xml; - right_xml.from_string(right_contents); + pugi::xml_document right_xml; + right_xml.load(right_contents.c_str()); - return compare_xml(left_xml.get_root(), right_xml.get_root()); + return compare_xml(left_xml.root(), right_xml.root()); } - static comparison_result compare_xml(const xlnt::xml_node &left, const xlnt::xml_node &right) + static comparison_result compare_xml(const pugi::xml_node &left, const pugi::xml_node &right) { - std::string left_temp = left.get_name(); - std::string right_temp = right.get_name(); + std::string left_temp = left.name(); + std::string right_temp = right.name(); if(left_temp != right_temp) { return {difference_type::names_differ, left_temp, right_temp}; } - for(auto &left_attribute : left.get_attributes()) + for(auto &left_attribute : left.attributes()) { - left_temp = left_attribute.second; - - if(!right.has_attribute(left_attribute.first)) + left_temp = left_attribute.name(); + + if(!right.attribute(left_attribute.name())) { return {difference_type::missing_attribute, left_temp, "((empty))"}; } - left_temp = left_attribute.second; - right_temp = right.get_attribute(left_attribute.first); + left_temp = left_attribute.name(); + right_temp = right.attribute(left_attribute.name()).name(); if(left_temp != right_temp) { @@ -96,34 +95,34 @@ public: } } - if(left.has_text()) + if(left.text()) { - left_temp = left.get_text(); + left_temp = left.text().get(); - if(!right.has_text()) + if(!right.text()) { return {difference_type::missing_text, left_temp, "((empty))"}; } - right_temp = right.get_text(); + right_temp = right.text().get(); if(left_temp != right_temp) { return {difference_type::text_values_differ, left_temp, right_temp}; } } - else if(right.has_text()) + else if(right.text()) { - right_temp = right.get_text(); + right_temp = right.text().get(); return {difference_type::text_values_differ, "((empty))", right_temp}; } - auto right_children = right.get_children(); + auto right_children = right.children(); auto right_child_iter = right_children.begin(); - for(auto left_child : left.get_children()) + for(auto left_child : left.children()) { - left_temp = left_child.get_name(); + left_temp = left_child.name(); if(right_child_iter == right_children.end()) { @@ -143,7 +142,7 @@ public: if(right_child_iter != right_children.end()) { - right_temp = right_child_iter->get_name(); + right_temp = right_child_iter->name(); return {difference_type::child_order_differs, "((end))", right_temp}; }