begin translating xml parsing and serialization to libstudxml

This commit is contained in:
Thomas Fussell 2016-09-16 22:59:13 -04:00
parent 044424a6f0
commit 45f61ee644
11 changed files with 490 additions and 357 deletions

5
.gitmodules vendored
View File

@ -12,3 +12,8 @@
path = third-party/utfcpp
url = https://github.com/nemtrif/utfcpp
branch = master
[submodule "third-party/pugixml"]
path = third-party/pugixml
url = https://github.com/zeux/pugixml
branch = master

View File

@ -28,7 +28,7 @@ include_directories(include)
include_directories(include/xlnt)
include_directories(source)
include_directories(third-party/miniz)
include_directories(third-party/pugixml/src)
include_directories(third-party/libstudxml)
include_directories(third-party/utfcpp/source)
FILE(GLOB ROOT_HEADERS include/xlnt/*.hpp)
@ -64,14 +64,13 @@ SET(SOURCES ${CELL_SOURCES} ${CHARTS_SOURCES} ${CHARTSHEET_SOURCES} ${DRAWING_SO
SET(MINIZ ../third-party/miniz/miniz.c ../third-party/miniz/miniz.h)
SET(PUGIXML ../third-party/pugixml/src/pugixml.hpp ../third-party/pugixml/src/pugixml.cpp ../third-party/pugixml/src/pugiconfig.hpp)
SET(LIBSTUDXML ../third-party/libstudxml/xml/parser.cxx)
if(SHARED)
add_library(xlnt.shared SHARED ${HEADERS} ${SOURCES} ${MINIZ} ${PUGIXML})
add_library(xlnt.shared SHARED ${HEADERS} ${SOURCES} ${MINIZ} ${LIBSTUDXML})
target_compile_definitions(xlnt.shared PRIVATE XLNT_SHARED=1)
if(MSVC)
target_compile_definitions(xlnt.shared PRIVATE XLNT_EXPORT=1)
target_compile_definitions(xlnt.shared PRIVATE PUGIXML_API=__declspec\(dllexport\))
set_target_properties(xlnt.shared PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\"")
endif()
install(TARGETS xlnt.shared
@ -102,7 +101,7 @@ if(SHARED)
endif()
if(STATIC)
add_library(xlnt.static STATIC ${HEADERS} ${SOURCES} ${MINIZ} ${PUGIXML})
add_library(xlnt.static STATIC ${HEADERS} ${SOURCES} ${MINIZ} ${LIBSTUDXML})
target_compile_definitions(xlnt.static PUBLIC XLNT_STATIC=1)
install(TARGETS xlnt.static
LIBRARY DESTINATION ${LIB_DEST_DIR}
@ -130,7 +129,7 @@ source_group(utils FILES ${UTILS_HEADERS} ${UTILS_SOURCES})
source_group(workbook FILES ${WORKBOOK_HEADERS} ${WORKBOOK_SOURCES})
source_group(worksheet FILES ${WORKSHEET_HEADERS} ${WORKSHEET_SOURCES})
source_group(third-party\\miniz FILES ${MINIZ})
source_group(third-party\\pugixml FILES ${PUGIXML})
source_group(third-party\\libstudxml FILES ${LIBSTUDXML})
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

View File

@ -22,9 +22,7 @@
// @author: see AUTHORS file
#pragma once
/// <summary>
/// Define this here so we don't have to modify pugiconfig.hpp in pugixml source tree.
/// </summary>
#define PUGIXML_HAS_LONG_LONG
#include <pugixml.hpp>
#include <xml/content>
#include <xml/parser>
#include <xml/qname>
#include <xml/serializer>

View File

@ -3,7 +3,6 @@
#include <detail/xlsx_consumer.hpp>
#include <detail/constants.hpp>
#include <detail/include_pugixml.hpp>
#include <detail/workbook_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/utils/path.hpp>
@ -222,20 +221,36 @@ std::string to_string(xlnt::border_side side)
}
}
xlnt::protection read_protection(const pugi::xml_node protection_node)
xlnt::protection read_protection(xml::parser &parser)
{
xlnt::protection prot;
prot.locked(is_true(protection_node.attribute("locked").value()));
prot.hidden(is_true(protection_node.attribute("hidden").value()));
for (auto event : parser)
{
if (event == xml::parser::event_type::start_attribute)
{
if (parser.name() == "locked")
{
prot.locked(is_true(parser.value()));
}
else if (parser.name() == "hidden")
{
prot.hidden(is_true(parser.value()));
}
}
else
{
break;
}
}
return prot;
}
xlnt::alignment read_alignment(const pugi::xml_node alignment_node)
xlnt::alignment read_alignment(xml::parser &parser)
{
xlnt::alignment align;
/*
align.wrap(is_true(alignment_node.attribute("wrapText").value()));
align.shrink(is_true(alignment_node.attribute("shrinkToFit").value()));
@ -250,14 +265,14 @@ xlnt::alignment read_alignment(const pugi::xml_node alignment_node)
std::string horizontal = alignment_node.attribute("horizontal").value();
align.horizontal(from_string<xlnt::horizontal_alignment>(horizontal));
}
*/
return align;
}
void read_number_formats(const pugi::xml_node number_formats_node, std::vector<xlnt::number_format> &number_formats)
void read_number_formats(xml::parser &parser, std::vector<xlnt::number_format> &number_formats)
{
number_formats.clear();
/*
for (auto num_fmt_node : number_formats_node.children("numFmt"))
{
std::string format_string(num_fmt_node.attribute("formatCode").value());
@ -274,12 +289,13 @@ void read_number_formats(const pugi::xml_node number_formats_node, std::vector<x
number_formats.push_back(nf);
}
*/
}
xlnt::color read_color(const pugi::xml_node &color_node)
xlnt::color read_color(xml::parser &parser)
{
xlnt::color result;
/*
if (color_node.attribute("auto"))
{
return result;
@ -302,14 +318,14 @@ xlnt::color read_color(const pugi::xml_node &color_node)
{
result.set_tint(color_node.attribute("tint").as_double());
}
*/
return result;
}
xlnt::font read_font(const pugi::xml_node font_node)
xlnt::font read_font(xml::parser &parser)
{
xlnt::font new_font;
/*
new_font.size(string_to_size_t(font_node.child("sz").attribute("val").value()));
new_font.name(font_node.child("name").attribute("val").value());
@ -376,42 +392,46 @@ xlnt::font read_font(const pugi::xml_node font_node)
new_font.underline(xlnt::font::underline_style::single);
}
}
*/
return new_font;
}
void read_fonts(const pugi::xml_node &fonts_node, std::vector<xlnt::font> &fonts)
void read_fonts(xml::parser &parser, std::vector<xlnt::font> &fonts)
{
fonts.clear();
/*
for (auto font_node : fonts_node.children())
{
fonts.push_back(read_font(font_node));
}
*/
}
void read_indexed_colors(const pugi::xml_node &indexed_colors_node, std::vector<xlnt::color> &colors)
void read_indexed_colors(xml::parser &parser, std::vector<xlnt::color> &colors)
{
/*
for (auto color_node : indexed_colors_node.children())
{
colors.push_back(read_color(color_node));
}
*/
}
void read_colors(const pugi::xml_node &colors_node, std::vector<xlnt::color> &colors)
void read_colors(xml::parser &parser, std::vector<xlnt::color> &colors)
{
colors.clear();
/*
if (colors_node.child("indexedColors"))
{
read_indexed_colors(colors_node.child("indexedColors"), colors);
}
*/
}
xlnt::fill read_fill(const pugi::xml_node &fill_node)
xlnt::fill read_fill(xml::parser &parser)
{
xlnt::fill new_fill;
/*
if (fill_node.child("patternFill"))
{
auto pattern_fill_node = fill_node.child("patternFill");
@ -462,25 +482,26 @@ xlnt::fill read_fill(const pugi::xml_node &fill_node)
new_fill = gradient;
}
*/
return new_fill;
}
void read_fills(const pugi::xml_node &fills_node, std::vector<xlnt::fill> &fills)
void read_fills(xml::parser &parser, std::vector<xlnt::fill> &fills)
{
fills.clear();
/*
for (auto fill_node : fills_node.children())
{
fills.emplace_back();
fills.back() = read_fill(fill_node);
}
*/
}
xlnt::border::border_property read_side(const pugi::xml_node &side_node)
xlnt::border::border_property read_side(xml::parser &parser)
{
xlnt::border::border_property new_side;
/*
if (side_node.attribute("style"))
{
new_side.style(from_string<xlnt::border_style>(side_node.attribute("style").value()));
@ -490,14 +511,14 @@ xlnt::border::border_property read_side(const pugi::xml_node &side_node)
{
new_side.color(read_color(side_node.child("color")));
}
*/
return new_side;
}
xlnt::border read_border(const pugi::xml_node &border_node)
xlnt::border read_border(xml::parser &parser)
{
xlnt::border new_border;
/*
for (const auto &side : xlnt::border::all_sides())
{
auto side_name = to_string(side);
@ -507,41 +528,53 @@ xlnt::border read_border(const pugi::xml_node &border_node)
new_border.side(side, read_side(border_node.child(side_name.c_str())));
}
}
*/
return new_border;
}
void read_borders(const pugi::xml_node &borders_node, std::vector<xlnt::border> &borders)
void read_borders(xml::parser &parser, std::vector<xlnt::border> &borders)
{
borders.clear();
/*
for (auto border_node : borders_node.children())
{
borders.push_back(read_border(border_node));
}
*/
}
std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt::zip_file &archive)
{
std::vector<xlnt::relationship> relationships;
if (!archive.has_file(part)) return relationships;
pugi::xml_document document;
document.load_string(archive.read(part).c_str());
std::istringstream rels_stream(archive.read(part));
xml::parser parser(rels_stream, part.string());
auto root_node = document.child("Relationships");
xlnt::uri source(part.string());
for (auto relationship_node : root_node.children("Relationship"))
{
std::string id(relationship_node.attribute("Id").value());
std::string type_string(relationship_node.attribute("Type").value());
auto type = from_string<xlnt::relationship::type>(type_string);
xlnt::uri target(relationship_node.attribute("Target").value());
const auto xmlns = xlnt::constants::get_namespace("relationships");
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationships");
parser.content(xml::content::complex);
relationships.push_back(xlnt::relationship(id, type, source, target, xlnt::target_mode::internal));
while (true)
{
if (parser.peek() == xml::parser::event_type::end_element) break;
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationship");
std::string id(parser.attribute("Id"));
std::string type_string(parser.attribute("Type"));
xlnt::uri target(parser.attribute("Target"));
relationships.emplace_back(id, from_string<xlnt::relationship::type>(type_string),
source, target, xlnt::target_mode::internal);
parser.next_expect(xml::parser::event_type::end_element,
xlnt::constants::get_namespace("relationships"), "Relationship");
}
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Relationships");
return relationships;
}
@ -594,56 +627,56 @@ void xlsx_consumer::populate_workbook()
for (const auto &rel : manifest.get_relationships(path("/")))
{
pugi::xml_document document;
document.load_string(source_.read(rel.get_target().get_path()).c_str());
std::istringstream parser_stream(source_.read(rel.get_target().get_path()));
xml::parser parser(parser_stream, rel.get_target().get_path().string());
switch (rel.get_type())
{
case relationship::type::core_properties:
read_core_properties(document.root());
read_core_properties(parser);
break;
case relationship::type::extended_properties:
read_extended_properties(document.root());
read_extended_properties(parser);
break;
case relationship::type::custom_properties:
read_custom_property(document.root());
read_custom_property(parser);
break;
case relationship::type::office_document:
check_document_type(manifest.get_content_type(rel.get_target().get_path()));
read_workbook(document.root());
read_workbook(parser);
break;
case relationship::type::calculation_chain:
read_calculation_chain(document.root());
read_calculation_chain(parser);
break;
case relationship::type::connections:
read_connections(document.root());
read_connections(parser);
break;
case relationship::type::custom_xml_mappings:
read_custom_xml_mappings(document.root());
read_custom_xml_mappings(parser);
break;
case relationship::type::external_workbook_references:
read_external_workbook_references(document.root());
read_external_workbook_references(parser);
break;
case relationship::type::metadata:
read_metadata(document.root());
read_metadata(parser);
break;
case relationship::type::pivot_table:
read_pivot_table(document.root());
read_pivot_table(parser);
break;
case relationship::type::shared_string_table:
read_shared_string_table(document.root());
read_shared_string_table(parser);
break;
case relationship::type::shared_workbook_revision_headers:
read_shared_workbook_revision_headers(document.root());
read_shared_workbook_revision_headers(parser);
break;
case relationship::type::styles:
read_stylesheet(document.root());
read_stylesheet(parser);
break;
case relationship::type::theme:
read_theme(document.root());
read_theme(parser);
break;
case relationship::type::volatile_dependencies:
read_volatile_dependencies(document.root());
read_volatile_dependencies(parser);
break;
default:
break;
@ -656,20 +689,20 @@ void xlsx_consumer::populate_workbook()
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
{
pugi::xml_document document;
path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
document.load_string(source_.read(part_path).c_str());
std::istringstream parser_stream(source_.read(part_path));
xml::parser parser(parser_stream, rel.get_target().get_path().string());
switch (rel.get_type())
{
case relationship::type::shared_string_table:
read_shared_string_table(document);
read_shared_string_table(parser);
break;
case relationship::type::styles:
read_stylesheet(document);
read_stylesheet(parser);
break;
case relationship::type::theme:
read_theme(document);
read_theme(parser);
break;
default:
break;
@ -679,21 +712,21 @@ void xlsx_consumer::populate_workbook()
// Second pass, read sheets themselves
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
{
pugi::xml_document document;
{
path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
document.load_string(source_.read(part_path).c_str());
std::istringstream parser_stream(source_.read(part_path));
xml::parser parser(parser_stream, rel.get_target().get_path().string());
switch (rel.get_type())
{
case relationship::type::chartsheet:
read_chartsheet(document.root(), rel.get_id());
read_chartsheet(rel.get_id(), parser);
break;
case relationship::type::dialogsheet:
read_dialogsheet(document.root(), rel.get_id());
read_dialogsheet(rel.get_id(), parser);
break;
case relationship::type::worksheet:
read_worksheet(document.root(), rel.get_id());
read_worksheet(rel.get_id(), parser);
break;
default:
break;
@ -714,25 +747,36 @@ void xlsx_consumer::read_manifest()
if (!source_.has_file(package_rels_path)) throw invalid_file("missing package rels");
auto package_rels = read_relationships(package_rels_path, source_);
pugi::xml_document document;
document.load_string(source_.read(path("[Content_Types].xml")).c_str());
const auto root_node = document.child("Types");
std::istringstream parser_stream(source_.read(path("[Content_Types].xml")));
xml::parser parser(parser_stream, "[Content_Types].xml");
auto &manifest = destination_.get_manifest();
const std::string xmlns = "http://schemas.openxmlformats.org/package/2006/content-types";
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Types");
parser.content(xml::content::complex);
for (const auto child : root_node.children())
while (true)
{
if (child.name() == std::string("Default"))
{
manifest.register_default_type(child.attribute("Extension").value(),
child.attribute("ContentType").value());
}
else if (child.name() == std::string("Override"))
{
path part(child.attribute("PartName").value());
manifest.register_override_type(part, child.attribute("ContentType").value());
}
if (parser.peek() == xml::parser::event_type::end_element) break;
parser.next_expect(xml::parser::event_type::start_element);
if (parser.name() == "Default")
{
manifest.register_default_type(parser.attribute("Extension"),
parser.attribute("ContentType"));
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Default");
}
else if (parser.name() == "Override")
{
manifest.register_override_type(path(parser.attribute("PartName")),
parser.attribute("ContentType"));
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Override");
}
}
parser.next_expect(xml::parser::event_type::end_element, xmlns, "Types");
for (const auto &package_rel : package_rels)
{
@ -765,8 +809,9 @@ void xlsx_consumer::read_manifest()
}
}
void xlsx_consumer::read_extended_properties(const pugi::xml_node root)
void xlsx_consumer::read_extended_properties(xml::parser &parser)
{
/*
for (auto property_node : root.child("Properties"))
{
std::string name(property_node.name());
@ -781,10 +826,12 @@ void xlsx_consumer::read_extended_properties(const pugi::xml_node root)
else if (name == "AppVersion") destination_.set_app_version(value);
else if (name == "Application") destination_.set_application(value);
}
*/
}
void xlsx_consumer::read_core_properties(const pugi::xml_node root)
void xlsx_consumer::read_core_properties(xml::parser &parser)
{
/*
for (auto property_node : root.child("cp:coreProperties"))
{
std::string name(property_node.name());
@ -795,19 +842,23 @@ void xlsx_consumer::read_core_properties(const pugi::xml_node root)
else if (name == "dcterms:created") destination_.set_created(w3cdtf_to_datetime(value));
else if (name == "dcterms:modified") destination_.set_modified(w3cdtf_to_datetime(value));
}
*/
}
void xlsx_consumer::read_custom_file_properties(const pugi::xml_node root)
void xlsx_consumer::read_custom_file_properties(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */document.append_child("customFileProperties");
document.append_child("customFileProperties");
*/
}
// Write SpreadsheetML-Specific Package Parts
void xlsx_consumer::read_workbook(const pugi::xml_node root)
void xlsx_consumer::read_workbook(xml::parser &parser)
{
/*
auto workbook_node = root.child("workbook");
if (workbook_node.attribute("xmlns:x15"))
@ -887,72 +938,90 @@ void xlsx_consumer::read_workbook(const pugi::xml_node root)
{
destination_.d_->has_arch_id_ = true;
}
*/
}
// Write Workbook Relationship Target Parts
void xlsx_consumer::read_calculation_chain(const pugi::xml_node root)
void xlsx_consumer::read_calculation_chain(xml::parser &parser)
{
}
void xlsx_consumer::read_chartsheet(const pugi::xml_node root, const std::string &title)
void xlsx_consumer::read_chartsheet(const std::string &title, xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("chartsheet");
document.append_child("chartsheet");
*/
}
void xlsx_consumer::read_connections(const pugi::xml_node root)
void xlsx_consumer::read_connections(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("connections");
document.append_child("connections");
*/
}
void xlsx_consumer::read_custom_property(const pugi::xml_node root)
void xlsx_consumer::read_custom_property(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("customProperty");
document.append_child("customProperty");
*/
}
void xlsx_consumer::read_custom_xml_mappings(const pugi::xml_node root)
void xlsx_consumer::read_custom_xml_mappings(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("connections");
document.append_child("connections");
*/
}
void xlsx_consumer::read_dialogsheet(const pugi::xml_node root, const std::string &title)
void xlsx_consumer::read_dialogsheet(const std::string &title, xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("dialogsheet");
document.append_child("dialogsheet");
*/
}
void xlsx_consumer::read_external_workbook_references(const pugi::xml_node root)
void xlsx_consumer::read_external_workbook_references(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("externalLink");
document.append_child("externalLink");
*/
}
void xlsx_consumer::read_metadata(const pugi::xml_node root)
void xlsx_consumer::read_metadata(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("metadata");
document.append_child("metadata");
*/
}
void xlsx_consumer::read_pivot_table(const pugi::xml_node root)
void xlsx_consumer::read_pivot_table(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("pivotTableDefinition");
document.append_child("pivotTableDefinition");
*/
}
void xlsx_consumer::read_shared_string_table(const pugi::xml_node root)
void xlsx_consumer::read_shared_string_table(xml::parser &parser)
{
/*
auto sst_node = root.child("sst");
std::size_t unique_count = 0;
@ -1025,31 +1094,39 @@ void xlsx_consumer::read_shared_string_table(const pugi::xml_node root)
{
throw invalid_file("sizes don't match");
}
*/
}
void xlsx_consumer::read_shared_workbook_revision_headers(const pugi::xml_node root)
void xlsx_consumer::read_shared_workbook_revision_headers(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("headers");
document.append_child("headers");
*/
}
void xlsx_consumer::read_shared_workbook(const pugi::xml_node root)
void xlsx_consumer::read_shared_workbook(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("revisions");
document.append_child("revisions");
*/
}
void xlsx_consumer::read_shared_workbook_user_data(const pugi::xml_node root)
void xlsx_consumer::read_shared_workbook_user_data(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("users");
document.append_child("users");
*/
}
void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
void xlsx_consumer::read_stylesheet(xml::parser &parser)
{
/*
auto stylesheet_node = root.child("styleSheet");
auto &stylesheet = destination_.impl().stylesheet_;
@ -1192,23 +1269,29 @@ void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
format.style(stylesheet.get_style(style_name));
}
}
*/
}
void xlsx_consumer::read_theme(const pugi::xml_node root)
void xlsx_consumer::read_theme(xml::parser &parser)
{
/*
root.child("theme");
destination_.set_theme(theme());
*/
}
void xlsx_consumer::read_volatile_dependencies(const pugi::xml_node root)
void xlsx_consumer::read_volatile_dependencies(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("volTypes");
document.append_child("volTypes");
*/
}
void xlsx_consumer::read_worksheet(const pugi::xml_node root, const std::string &rel_id)
void xlsx_consumer::read_worksheet(const std::string &title, xml::parser &parser)
{
/*
auto title = std::find_if(destination_.d_->sheet_title_rel_id_map_.begin(),
destination_.d_->sheet_title_rel_id_map_.end(),
[&](const std::pair<std::string, std::string> &p)
@ -1425,38 +1508,47 @@ void xlsx_consumer::read_worksheet(const pugi::xml_node root, const std::string
ws.set_page_margins(margins);
}
*/
}
// Sheet Relationship Target Parts
void xlsx_consumer::read_comments(const pugi::xml_node root)
void xlsx_consumer::read_comments(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("comments");
document.append_child("comments");
*/
}
void xlsx_consumer::read_drawings(const pugi::xml_node root)
void xlsx_consumer::read_drawings(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("wsDr");
document.append_child("wsDr");
*/
}
// Unknown Parts
void xlsx_consumer::read_unknown_parts(const pugi::xml_node root)
void xlsx_consumer::read_unknown_parts(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("Hmm");
document.append_child("Hmm");
*/
}
void xlsx_consumer::read_unknown_relationships(const pugi::xml_node root)
void xlsx_consumer::read_unknown_relationships(xml::parser &parser)
{
/*
pugi::xml_document document;
document.load_string(source_.read(path("[Content Types].xml")).c_str());
/*auto root_node = */ document.append_child("Relationships");
document.append_child("Relationships");
*/
}
} // namespace detail

View File

@ -28,7 +28,7 @@
#include <unordered_map>
#include <vector>
#include <detail/include_pugixml.hpp>
#include <detail/include_libstudxml.hpp>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/packaging/zip_file.hpp>
@ -65,44 +65,44 @@ private:
void read_manifest();
void read_core_properties(const pugi::xml_node root);
void read_extended_properties(const pugi::xml_node root);
void read_custom_file_properties(const pugi::xml_node root);
void read_core_properties(xml::parser &parser);
void read_extended_properties(xml::parser &parser);
void read_custom_file_properties(xml::parser &parser);
// SpreadsheetML-Specific Package Parts
void read_workbook(const pugi::xml_node root);
void read_workbook(xml::parser &parser);
// Workbook Relationship Target Parts
void read_calculation_chain(const pugi::xml_node root);
void read_connections(const pugi::xml_node root);
void read_custom_property(const pugi::xml_node root);
void read_custom_xml_mappings(const pugi::xml_node root);
void read_external_workbook_references(const pugi::xml_node root);
void read_metadata(const pugi::xml_node root);
void read_pivot_table(const pugi::xml_node root);
void read_shared_string_table(const pugi::xml_node root);
void read_shared_workbook_revision_headers(const pugi::xml_node root);
void read_shared_workbook(const pugi::xml_node root);
void read_shared_workbook_user_data(const pugi::xml_node root);
void read_stylesheet(const pugi::xml_node root);
void read_theme(const pugi::xml_node root);
void read_volatile_dependencies(const pugi::xml_node root);
void read_calculation_chain(xml::parser &parser);
void read_connections(xml::parser &parser);
void read_custom_property(xml::parser &parser);
void read_custom_xml_mappings(xml::parser &parser);
void read_external_workbook_references(xml::parser &parser);
void read_metadata(xml::parser &parser);
void read_pivot_table(xml::parser &parser);
void read_shared_string_table(xml::parser &parser);
void read_shared_workbook_revision_headers(xml::parser &parser);
void read_shared_workbook(xml::parser &parser);
void read_shared_workbook_user_data(xml::parser &parser);
void read_stylesheet(xml::parser &parser);
void read_theme(xml::parser &parser);
void read_volatile_dependencies(xml::parser &parser);
void read_chartsheet(const pugi::xml_node root, const std::string &title);
void read_dialogsheet(const pugi::xml_node root, const std::string &title);
void read_worksheet(const pugi::xml_node root, const std::string &title);
void read_chartsheet(const std::string &title, xml::parser &parser);
void read_dialogsheet(const std::string &title, xml::parser &parser);
void read_worksheet(const std::string &title, xml::parser &parser);
// Sheet Relationship Target Parts
void read_comments(const pugi::xml_node root);
void read_drawings(const pugi::xml_node root);
void read_comments(xml::parser &parser);
void read_drawings(xml::parser &parser);
// Unknown Parts
void read_unknown_parts(const pugi::xml_node root);
void read_unknown_relationships(const pugi::xml_node root);
void read_unknown_parts(xml::parser &parser);
void read_unknown_relationships(xml::parser &parser);
/// <summary>
/// A reference to the archive from which files representing the workbook

View File

@ -2,7 +2,6 @@
#include <detail/xlsx_producer.hpp>
#include <detail/constants.hpp>
#include <detail/include_pugixml.hpp>
#include <detail/workbook_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/utils/path.hpp>
@ -23,17 +22,6 @@ bool is_integral(long double d)
return d == static_cast<long long int>(d);
}
/// <summary>
/// Serializes document and writes to to the archive at archive_path.
/// </summary>
void write_document_to_archive(const pugi::xml_document &document,
const xlnt::path &archive_path, xlnt::zip_file &archive)
{
std::ostringstream out_stream;
document.save(out_stream);
archive.write_string(out_stream.str(), archive_path);
}
std::string fill(const std::string &string, std::size_t length = 2)
{
if (string.size() >= length)
@ -195,78 +183,78 @@ std::string to_string(xlnt::border_side side)
}
}
void write_relationships(const std::vector<xlnt::relationship> &relationships, pugi::xml_node root)
void write_relationships(const std::vector<xlnt::relationship> &relationships, xml::serializer &serializer)
{
auto relationships_node = root.append_child("Relationships");
relationships_node.append_attribute("xmlns").set_value(xlnt::constants::get_namespace("relationships").c_str());
const auto xmlns = xlnt::constants::get_namespace("relationships");
serializer.start_element(xmlns, "Relationships");
serializer.namespace_decl(xmlns, "");
for (const auto &relationship : relationships)
{
auto relationship_node = relationships_node.append_child("Relationship");
serializer.start_element(xmlns, "Relationship");
relationship_node.append_attribute("Id").set_value(relationship.get_id().c_str());
relationship_node.append_attribute("Type").set_value(to_string(relationship.get_type()).c_str());
relationship_node.append_attribute("Target").set_value(relationship.get_target().get_path().string().c_str());
serializer.attribute("Id", relationship.get_id());
serializer.attribute("Type", to_string(relationship.get_type()));
serializer.attribute("Target", relationship.get_target().get_path().string());
if (relationship.get_target_mode() == xlnt::target_mode::external)
{
relationship_node.append_attribute("TargetMode").set_value("External");
serializer.attribute("TargetMode", "External");
}
serializer.end_element(xmlns, "Relationship");
}
serializer.end_element(xmlns, "Relationships");
}
bool write_color(const xlnt::color &color, pugi::xml_node color_node)
bool write_color(const xlnt::color &color, xml::serializer &serializer)
{
switch (color.get_type())
{
case xlnt::color::type::theme:
color_node.append_attribute("theme")
.set_value(std::to_string(color.get_theme().get_index()).c_str());
serializer.attribute("theme", std::to_string(color.get_theme().get_index()));
break;
case xlnt::color::type::indexed:
color_node.append_attribute("indexed")
.set_value(std::to_string(color.get_indexed().get_index()).c_str());
serializer.attribute("indexed", std::to_string(color.get_indexed().get_index()));
break;
case xlnt::color::type::rgb:
default:
color_node.append_attribute("rgb")
.set_value(color.get_rgb().get_hex_string().c_str());
serializer.attribute("rgb", color.get_rgb().get_hex_string());
break;
}
return true;
}
bool write_dxfs(pugi::xml_node &dxfs_node)
void write_dxfs(xml::serializer &serializer)
{
dxfs_node.append_attribute("count").set_value("0");
return true;
serializer.attribute("count", "0");
}
bool write_table_styles(pugi::xml_node &table_styles_node)
void write_table_styles(xml::serializer &serializer)
{
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;
serializer.attribute("count", "0");
serializer.attribute("defaultTableStyle", "TableStyleMedium9");
serializer.attribute("defaultPivotStyle", "PivotStyleMedium7");
}
bool write_colors(const std::vector<xlnt::color> &colors, pugi::xml_node &colors_node)
void write_colors(const std::vector<xlnt::color> &colors, xml::serializer &serializer)
{
auto indexed_colors_node = colors_node.append_child("indexedColors");
serializer.start_element("indexedColors");
for (auto &c : colors)
{
auto rgb_color_node = indexed_colors_node.append_child("rgbColor");
auto rgb_attribute = rgb_color_node.append_attribute("rgb");
rgb_attribute.set_value(c.get_rgb().get_hex_string().c_str());
serializer.start_element("rgbColor");
serializer.attribute("rgb", c.get_rgb().get_hex_string());
serializer.end_element();
}
return true;
serializer.end_element();
}
} // namespace
@ -304,25 +292,27 @@ void xlsx_producer::populate_archive()
for (auto &rel : source_.impl().manifest_.get_relationships(path("/")))
{
pugi::xml_document document;
std::ostringstream serializer_stream;
xml::serializer serializer(serializer_stream, rel.get_target().get_path().string());
bool write_document = true;
switch (rel.get_type())
{
case relationship::type::core_properties:
write_core_properties(rel, document.root());
write_core_properties(rel, serializer);
break;
case relationship::type::extended_properties:
write_extended_properties(rel, document.root());
write_extended_properties(rel, serializer);
break;
case relationship::type::custom_properties:
write_custom_properties(rel, document.root());
write_custom_properties(rel, serializer);
break;
case relationship::type::office_document:
write_workbook(rel, document.root());
write_workbook(rel, serializer);
break;
case relationship::type::thumbnail:
@ -336,7 +326,7 @@ void xlsx_producer::populate_archive()
if (write_document)
{
write_document_to_archive(document, rel.get_target().get_path(), destination_);
destination_.write_string(serializer_stream.str(), rel.get_target().get_path());
}
}
@ -350,26 +340,33 @@ void xlsx_producer::populate_archive()
void xlsx_producer::write_manifest()
{
pugi::xml_document content_types_document;
std::ostringstream content_types_stream;
xml::serializer content_types_serializer(content_types_stream, "[Content_Types].xml");
auto types_node = content_types_document.append_child("Types");
types_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/package/2006/content-types");
const auto xmlns = std::string("http://schemas.openxmlformats.org/package/2006/content-types");
content_types_serializer.start_element(xmlns, "Types");
content_types_serializer.namespace_decl(xmlns, "");
for (const auto &extension : source_.get_manifest().get_extensions_with_default_types())
{
auto default_node = types_node.append_child("Default");
default_node.append_attribute("Extension").set_value(extension.c_str());
auto content_type = source_.get_manifest().get_default_type(extension);
default_node.append_attribute("ContentType").set_value(content_type.c_str());
content_types_serializer.start_element(xmlns, "Default");
content_types_serializer.attribute("Extension", extension);
content_types_serializer.attribute("ContentType",
source_.get_manifest().get_default_type(extension));
content_types_serializer.end_element(xmlns, "Default");
}
for (const auto &part : source_.get_manifest().get_parts_with_overriden_types())
{
auto override_node = types_node.append_child("Override");
override_node.append_attribute("PartName").set_value(part.resolve(path("/")).string().c_str());
auto content_type = source_.get_manifest().get_override_type(part);
override_node.append_attribute("ContentType").set_value(content_type.c_str());
content_types_serializer.start_element(xmlns, "Override");
content_types_serializer.attribute("PartName", part.resolve(path("/")).string());
content_types_serializer.attribute("ContentType",
source_.get_manifest().get_override_type(part));
content_types_serializer.end_element(xmlns, "Override");
}
content_types_serializer.end_element(xmlns, "Types");
for (const auto &part : source_.get_manifest().get_parts())
{
@ -377,8 +374,6 @@ void xlsx_producer::write_manifest()
if (part_rels.empty()) continue;
pugi::xml_document part_rels_document;
write_relationships(part_rels, part_rels_document.root());
path parent = part.parent();
if (parent.is_absolute())
@ -386,24 +381,29 @@ void xlsx_producer::write_manifest()
parent = path(parent.string().substr(1));
}
std::ostringstream rels_stream;
path rels_path(parent.append("_rels").append(part.filename() + ".rels").string());
write_document_to_archive(part_rels_document, rels_path, destination_);
xml::serializer rels_serializer(rels_stream, rels_path.string());
write_relationships(part_rels, rels_serializer);
destination_.write_string(rels_stream.str(), rels_path);
}
write_document_to_archive(content_types_document, path("[Content_Types].xml"), destination_);
destination_.write_string(content_types_stream.str(), path("[Content_Types].xml"));
}
void xlsx_producer::write_extended_properties(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_extended_properties(const relationship &rel, xml::serializer &serializer)
{
auto properties_node = root.append_child("Properties");
serializer.start_element("Properties");
properties_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
properties_node.append_attribute("xmlns:vt").set_value("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
properties_node.append_child("Application").text().set(source_.get_application().c_str());
properties_node.append_child("DocSecurity").text().set(std::to_string(source_.get_doc_security()).c_str());
properties_node.append_child("ScaleCrop").text().set(source_.get_scale_crop() ? "true" : "false");
serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties", "xmlns");
serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt");
serializer.element("Application", source_.get_application());
serializer.element("DocSecurity", std::to_string(source_.get_doc_security()));
serializer.element("ScaleCrop", source_.get_scale_crop() ? "true" : "false");
/*
auto heading_pairs_node = properties_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");
@ -434,10 +434,12 @@ void xlsx_producer::write_extended_properties(const relationship &rel, pugi::xml
properties_node.append_child("SharedDoc").text().set(source_.is_shared_doc() ? "true" : "false");
properties_node.append_child("HyperlinksChanged").text().set(source_.hyperlinks_changed() ? "true" : "false");
properties_node.append_child("AppVersion").text().set(source_.get_app_version().c_str());
*/
}
void xlsx_producer::write_core_properties(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_core_properties(const relationship &rel, xml::serializer &serializer)
{
/*
auto core_properties_node = root.append_child("cp:coreProperties");
core_properties_node.append_attribute("xmlns:cp").set_value("http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
@ -457,7 +459,7 @@ void xlsx_producer::write_core_properties(const relationship &rel, pugi::xml_nod
{
core_properties_node.append_child("dc:title").text().set(source_.get_title().c_str());
}
*/
/*
core_properties_node.append_child("dc:description");
core_properties_node.append_child("dc:subject");
@ -466,14 +468,14 @@ void xlsx_producer::write_core_properties(const relationship &rel, pugi::xml_nod
*/
}
void xlsx_producer::write_custom_properties(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_custom_properties(const relationship &rel, xml::serializer &serializer)
{
/*auto properties_node = */root.append_child("Properties");
serializer.element("Properties");
}
// Write SpreadsheetML-Specific Package Parts
void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &serializer)
{
std::size_t num_visible = 0;
bool any_defined_names = false;
@ -496,18 +498,19 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
throw no_visible_worksheets();
}
auto workbook_node = root.append_child("workbook");
const auto xmlns = std::string("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
workbook_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
workbook_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
serializer.start_element(xmlns, "workbook");
serializer.namespace_decl(xmlns, "");
serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
if (source_.x15_enabled())
{
workbook_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006");
workbook_node.append_attribute("mc:Ignorable").set_value("x15");
workbook_node.append_attribute("xmlns:x15").set_value("http://schemas.microsoft.com/office/spreadsheetml/2010/11/main");
serializer.namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc");
serializer.attribute("mc:Ignorable", "x15");
serializer.namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2010/11/main", "x15");
}
/*
if (source_.has_file_version())
{
auto file_version_node = workbook_node.append_child("fileVersion");
@ -527,10 +530,8 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
workbook_pr_node.append_attribute("codeName").set_value(source_.get_code_name().c_str());
}
/*
workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226");
workbook_pr_node.append_attribute("date1904").set_value(source_.get_base_date() == calendar::mac_1904 ? "1" : "0");
*/
// workbook_pr_node.append_attribute("defaultThemeVersion").set_value("124226");
// workbook_pr_node.append_attribute("date1904").set_value(source_.get_base_date() == calendar::mac_1904 ? "1" : "0");
}
if (source_.has_absolute_path())
@ -570,31 +571,32 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
workbook_view_node.append_attribute("windowHeight").set_value(std::to_string(view.window_height).c_str());
workbook_view_node.append_attribute("tabRatio").set_value(std::to_string(view.tab_ratio).c_str());
}
*/
auto sheets_node = workbook_node.append_child("sheets");
pugi::xml_node defined_names_node;
serializer.start_element(xmlns, "sheets");
/*
if (any_defined_names)
{
defined_names_node = workbook_node.append_child("definedNames");
}
*/
for (const auto ws : source_)
{
auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.get_title()];
auto sheet_rel = source_.d_->manifest_.get_relationship(rel.get_source().get_path(), sheet_rel_id);
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(ws.get_id()).c_str());
serializer.start_element(xmlns, "sheet");
serializer.attribute("name", ws.get_title());
serializer.attribute("sheetId", std::to_string(ws.get_id()));
if (ws.has_page_setup() && ws.get_sheet_state() == xlnt::sheet_state::hidden)
{
sheet_node.append_attribute("state").set_value("hidden");
serializer.attribute("state", "hidden");
}
sheet_node.append_attribute("r:id").set_value(sheet_rel_id.c_str());
serializer.attribute("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id", sheet_rel_id);
/*
if (ws.has_auto_filter())
{
auto defined_name_node = defined_names_node.append_child("definedName");
@ -605,8 +607,11 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
"'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string();
defined_name_node.text().set(name.c_str());
}
*/
serializer.end_element(xmlns, "sheet");
}
/*
if (source_.has_calculation_properties())
{
auto calc_pr_node = workbook_node.append_child("calcPr");
@ -643,67 +648,72 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
auto arch_id_node = ext_node.append_child("mx:ArchID");
arch_id_node.append_attribute("Flags").set_value("2");
}
*/
serializer.end_element(xmlns, "sheets");
serializer.end_element(xmlns, "workbook");
for (const auto &child_rel : source_.get_manifest().get_relationships(rel.get_target().get_path()))
{
pugi::xml_document document;
std::ostringstream child_stream;
xml::serializer child_serializer(child_stream, child_rel.get_target().get_path().string());
switch (child_rel.get_type())
{
case relationship::type::calculation_chain:
write_calculation_chain(child_rel, document.root());
write_calculation_chain(child_rel, child_serializer);
break;
case relationship::type::chartsheet:
write_chartsheet(child_rel, document.root());
write_chartsheet(child_rel, child_serializer);
break;
case relationship::type::connections:
write_connections(child_rel, document.root());
write_connections(child_rel, child_serializer);
break;
case relationship::type::custom_xml_mappings:
write_custom_xml_mappings(child_rel, document.root());
write_custom_xml_mappings(child_rel, child_serializer);
break;
case relationship::type::dialogsheet:
write_dialogsheet(child_rel, document.root());
write_dialogsheet(child_rel, child_serializer);
break;
case relationship::type::external_workbook_references:
write_external_workbook_references(child_rel, document.root());
write_external_workbook_references(child_rel, child_serializer);
break;
case relationship::type::metadata:
write_metadata(child_rel, document.root());
write_metadata(child_rel, child_serializer);
break;
case relationship::type::pivot_table:
write_pivot_table(child_rel, document.root());
write_pivot_table(child_rel, child_serializer);
break;
case relationship::type::shared_string_table:
write_shared_string_table(child_rel, document.root());
write_shared_string_table(child_rel, child_serializer);
break;
case relationship::type::shared_workbook_revision_headers:
write_shared_workbook_revision_headers(child_rel, document.root());
write_shared_workbook_revision_headers(child_rel, child_serializer);
break;
case relationship::type::styles:
write_styles(child_rel, document.root());
write_styles(child_rel, child_serializer);
break;
case relationship::type::theme:
write_theme(child_rel, document.root());
write_theme(child_rel, child_serializer);
break;
case relationship::type::volatile_dependencies:
write_volatile_dependencies(child_rel, document.root());
write_volatile_dependencies(child_rel, child_serializer);
break;
case relationship::type::worksheet:
write_worksheet(child_rel, document.root());
write_worksheet(child_rel, child_serializer);
break;
default:
@ -711,56 +721,56 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
}
path archive_path(child_rel.get_source().get_path().parent().append(child_rel.get_target().get_path()));
write_document_to_archive(document, archive_path, destination_);
destination_.write_string(child_stream.str(), archive_path);
}
}
// Write Workbook Relationship Target Parts
void xlsx_producer::write_calculation_chain(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_calculation_chain(const relationship &rel, xml::serializer &serializer)
{
/*auto calc_chain_node = */root.append_child("calcChain");
serializer.start_element("calcChain");
}
void xlsx_producer::write_chartsheet(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_chartsheet(const relationship &rel, xml::serializer &serializer)
{
/*auto chartsheet_node = */root.append_child("chartsheet");
serializer.start_element("chartsheet");
}
void xlsx_producer::write_connections(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_connections(const relationship &rel, xml::serializer &serializer)
{
/*auto connections_node = */root.append_child("connections");
serializer.start_element("connections");
}
void xlsx_producer::write_custom_xml_mappings(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_custom_xml_mappings(const relationship &rel, xml::serializer &serializer)
{
/*auto map_info_node = */root.append_child("MapInfo");
serializer.start_element("MapInfo");
}
void xlsx_producer::write_dialogsheet(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_dialogsheet(const relationship &rel, xml::serializer &serializer)
{
/*auto dialogsheet_node = */root.append_child("dialogsheet");
serializer.start_element("dialogsheet");
}
void xlsx_producer::write_external_workbook_references(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_external_workbook_references(const relationship &rel, xml::serializer &serializer)
{
/*auto external_link_node = */root.append_child("externalLink");
serializer.start_element("externalLink");
}
void xlsx_producer::write_metadata(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_metadata(const relationship &rel, xml::serializer &serializer)
{
/*auto metadata_node = */root.append_child("metadata");
serializer.start_element("metadata");
}
void xlsx_producer::write_pivot_table(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_pivot_table(const relationship &rel, xml::serializer &serializer)
{
/*auto pivot_table_definition_node = */root.append_child("pivotTableDefinition");
serializer.start_element("pivotTableDefinition");
}
void xlsx_producer::write_shared_string_table(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_shared_string_table(const relationship &rel, xml::serializer &serializer)
{
auto sst_node = root.append_child("sst");
serializer.start_element("sst");
/*
sst_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
std::size_t string_count = 0;
@ -830,27 +840,28 @@ void xlsx_producer::write_shared_string_table(const relationship &rel, pugi::xml
}
}
}
*/
}
void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel, xml::serializer &serializer)
{
/*auto headers_node = */root.append_child("headers");
serializer.start_element("headers");
}
void xlsx_producer::write_shared_workbook(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_shared_workbook(const relationship &rel, xml::serializer &serializer)
{
/*auto revisions_node = */root.append_child("revisions");
serializer.start_element("revisions");
}
void xlsx_producer::write_shared_workbook_user_data(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_shared_workbook_user_data(const relationship &rel, xml::serializer &serializer)
{
/*auto users_node = */root.append_child("users");
serializer.start_element("users");
}
void xlsx_producer::write_styles(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_styles(const relationship &rel, xml::serializer &serializer)
{
auto stylesheet_node = root.append_child("styleSheet");
serializer.start_element("styleSheet");
/*
// Namespaces
stylesheet_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
@ -1295,11 +1306,13 @@ void xlsx_producer::write_styles(const relationship &rel, pugi::xml_node root)
ext_node.append_attribute("xmlns:x14").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
auto slicer_styles_node = ext_node.append_child("x14:slicerStyles");
slicer_styles_node.append_attribute("defaultSlicerStyle").set_value("SlicerStyleLight1");
*/
}
void xlsx_producer::write_theme(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_theme(const relationship &rel, xml::serializer &serializer)
{
auto theme_node = root.append_child("a:theme");
serializer.start_element("a:theme");
/*
theme_node.append_attribute("xmlns:a").set_value(constants::get_namespace("drawingml").c_str());
theme_node.append_attribute("name").set_value("Office Theme");
@ -1602,14 +1615,15 @@ void xlsx_producer::write_theme(const relationship &rel, pugi::xml_node root)
theme_family_node.append_attribute("name").set_value("Office Theme");
theme_family_node.append_attribute("id").set_value("{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}");
theme_family_node.append_attribute("vid").set_value("{4A3C46E8-61CC-4603-A589-7422A47A8E4A}");
*/
}
void xlsx_producer::write_volatile_dependencies(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_volatile_dependencies(const relationship &rel, xml::serializer &serializer)
{
/*auto vol_types_node = */root.append_child("volTypes");
serializer.start_element("volTypes");
}
void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &serializer)
{
auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(),
source_.d_->sheet_title_rel_id_map_.end(),
@ -1620,17 +1634,19 @@ void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root
auto ws = source_.get_sheet_by_title(title);
auto worksheet_node = root.append_child("worksheet");
worksheet_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
worksheet_node.append_attribute("xmlns:r").set_value("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
const auto xmlns = std::string("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
serializer.start_element(xmlns, "worksheet");
serializer.namespace_decl(xmlns, "");
serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
if (ws.x14ac_enabled())
{
worksheet_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006");
worksheet_node.append_attribute("mc:Ignorable").set_value("x14ac");
worksheet_node.append_attribute("xmlns:x14ac").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
serializer.namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc");
serializer.attribute("mc:Ignorable", "x14ac");
serializer.namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac", "x14ac");
}
/*
if (ws.has_page_setup())
{
auto sheet_pr_node = worksheet_node.append_child("sheetPr");
@ -1766,12 +1782,13 @@ void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root
col_node.append_attribute("customWidth").set_value(props.custom ? "1" : "0");
}
}
*/
std::unordered_map<std::string, std::string> hyperlink_references;
auto sheet_data_node = worksheet_node.append_child("sheetData");
serializer.start_element(xmlns, "sheetData");
const auto &shared_strings = ws.get_workbook().get_shared_strings();
/*
for (auto row : ws.rows())
{
auto min = static_cast<xlnt::row_t>(row.num_cells());
@ -1916,7 +1933,9 @@ void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root
}
}
}
*/
serializer.end_element();
/*
if (ws.has_auto_filter())
{
auto auto_filter_node = worksheet_node.append_child("autoFilter");
@ -2034,31 +2053,34 @@ void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root
"Text &P of &N";
odd_footer_node.text().set(footer_text.c_str());
}
*/
serializer.end_element();
}
// Sheet Relationship Target Parts
void xlsx_producer::write_comments(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_comments(const relationship &rel, xml::serializer &serializer)
{
/*auto comments_node = */root.append_child("comments");
serializer.start_element("comments");
}
void xlsx_producer::write_drawings(const relationship &rel, pugi::xml_node root)
void xlsx_producer::write_drawings(const relationship &rel, xml::serializer &serializer)
{
/*auto ws_dr_node = */root.append_child("wsDr");
serializer.start_element("wsDr");
}
// Other Parts
void xlsx_producer::write_custom_property()
void xlsx_producer::write_custom_property(xml::serializer &serializer)
{
}
void xlsx_producer::write_unknown_parts()
void xlsx_producer::write_unknown_parts(xml::serializer &serializer)
{
}
void xlsx_producer::write_unknown_relationships()
void xlsx_producer::write_unknown_relationships(xml::serializer &serializer)
{
}

View File

@ -27,7 +27,7 @@
#include <iostream>
#include <vector>
#include <detail/include_pugixml.hpp>
#include <detail/include_libstudxml.hpp>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/packaging/zip_file.hpp>
@ -63,45 +63,45 @@ private:
// Package Parts
void write_manifest();
void write_core_properties(const relationship &rel, pugi::xml_node root);
void write_extended_properties(const relationship &rel, pugi::xml_node root);
void write_custom_properties(const relationship &rel, pugi::xml_node root);
void write_core_properties(const relationship &rel, xml::serializer &serializer);
void write_extended_properties(const relationship &rel, xml::serializer &serializer);
void write_custom_properties(const relationship &rel, xml::serializer &serializer);
void write_thumbnail(const relationship &rel);
// SpreadsheetML-Specific Package Parts
void write_workbook(const relationship &rel, pugi::xml_node root);
void write_workbook(const relationship &rel, xml::serializer &serializer);
// Workbook Relationship Target Parts
void write_calculation_chain(const relationship &rel, pugi::xml_node root);
void write_connections(const relationship &rel, pugi::xml_node root);
void write_custom_xml_mappings(const relationship &rel, pugi::xml_node root);
void write_external_workbook_references(const relationship &rel, pugi::xml_node root);
void write_metadata(const relationship &rel, pugi::xml_node root);
void write_pivot_table(const relationship &rel, pugi::xml_node root);
void write_shared_string_table(const relationship &rel, pugi::xml_node root);
void write_shared_workbook_revision_headers(const relationship &rel, pugi::xml_node root);
void write_shared_workbook(const relationship &rel, pugi::xml_node root);
void write_shared_workbook_user_data(const relationship &rel, pugi::xml_node root);
void write_styles(const relationship &rel, pugi::xml_node root);
void write_theme(const relationship &rel, pugi::xml_node root);
void write_volatile_dependencies(const relationship &rel, pugi::xml_node root);
void write_calculation_chain(const relationship &rel, xml::serializer &serializer);
void write_connections(const relationship &rel, xml::serializer &serializer);
void write_custom_xml_mappings(const relationship &rel, xml::serializer &serializer);
void write_external_workbook_references(const relationship &rel, xml::serializer &serializer);
void write_metadata(const relationship &rel, xml::serializer &serializer);
void write_pivot_table(const relationship &rel, xml::serializer &serializer);
void write_shared_string_table(const relationship &rel, xml::serializer &serializer);
void write_shared_workbook_revision_headers(const relationship &rel, xml::serializer &serializer);
void write_shared_workbook(const relationship &rel, xml::serializer &serializer);
void write_shared_workbook_user_data(const relationship &rel, xml::serializer &serializer);
void write_styles(const relationship &rel, xml::serializer &serializer);
void write_theme(const relationship &rel, xml::serializer &serializer);
void write_volatile_dependencies(const relationship &rel, xml::serializer &serializer);
void write_chartsheet(const relationship &rel, pugi::xml_node root);
void write_dialogsheet(const relationship &rel, pugi::xml_node root);
void write_worksheet(const relationship &rel, pugi::xml_node root);
void write_chartsheet(const relationship &rel, xml::serializer &serializer);
void write_dialogsheet(const relationship &rel, xml::serializer &serializer);
void write_worksheet(const relationship &rel, xml::serializer &serializer);
// Sheet Relationship Target Parts
void write_comments(const relationship &rel, pugi::xml_node root);
void write_drawings(const relationship &rel, pugi::xml_node root);
void write_comments(const relationship &rel, xml::serializer &serializer);
void write_drawings(const relationship &rel, xml::serializer &serializer);
// Other Parts
void write_custom_property();
void write_unknown_parts();
void write_unknown_relationships();
void write_custom_property(xml::serializer &serializer);
void write_unknown_parts(xml::serializer &serializer);
void write_unknown_relationships(xml::serializer &serializer);
// Helpers

View File

@ -0,0 +1,15 @@
/* file : xml/details/config.h.in
* copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
* license : MIT; see accompanying LICENSE file
*/
/* This file is automatically processed by configure. */
#ifndef XML_DETAILS_CONFIG_H
#define XML_DETAILS_CONFIG_H
#undef LIBSTUDXML_STATIC_LIB
#undef LIBSTUDXML_EXTERNAL_EXPAT
#undef LIBSTUDXML_BYTEORDER
#endif /* XML_DETAILS_CONFIG_H */

View File

@ -1,7 +1,6 @@
#pragma once
#include <iostream>
#include <pugixml.hpp>
#include <cxxtest/TestSuite.h>
#include <xlnt/xlnt.hpp>

View File

@ -16,6 +16,8 @@ public:
{
std::vector<std::uint8_t> buffer;
wb.save(buffer);
wb.save("a.xlsx");
xlnt::zip_file wb_archive(buffer);
xlnt::zip_file file_archive(file);

1
third-party/pugixml vendored Submodule

@ -0,0 +1 @@
Subproject commit dfe9360cdf038c0ecf53d45bfc75cf8fd34604b8