mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
begin cleaning up xml handling in consumer
This commit is contained in:
parent
8bd725f2fa
commit
dab1b0218d
|
@ -88,7 +88,7 @@ public:
|
||||||
/// Returns the canonical path of the chain of relationships by traversing through rels
|
/// Returns the canonical path of the chain of relationships by traversing through rels
|
||||||
/// and forming the absolute combined path.
|
/// and forming the absolute combined path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
path canonicalize(const std::vector<relationship> &rels);
|
path canonicalize(const std::vector<relationship> &rels) const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -83,7 +83,7 @@ enum class XLNT_API relationship_type
|
||||||
revision_log,
|
revision_log,
|
||||||
shared_workbook_user_data,
|
shared_workbook_user_data,
|
||||||
single_cell_table_definitions,
|
single_cell_table_definitions,
|
||||||
styles,
|
stylesheet,
|
||||||
table_definition,
|
table_definition,
|
||||||
vml_drawing,
|
vml_drawing,
|
||||||
volatile_dependencies,
|
volatile_dependencies,
|
||||||
|
|
|
@ -77,9 +77,9 @@ const std::unordered_map<std::string, std::string> &constants::get_namespaces()
|
||||||
{ "core-properties", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" },
|
{ "core-properties", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" },
|
||||||
{ "extended-properties", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" },
|
{ "extended-properties", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" },
|
||||||
|
|
||||||
{ "encryption", "http://schemas.microsoft.com/office/2006/encryption" },
|
{ "encryption", "http://schemas.microsoft.com/office/2006/encryption" },
|
||||||
{ "encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password" },
|
{ "encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password" },
|
||||||
{ "encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate" },
|
{ "encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate" },
|
||||||
|
|
||||||
{ "dc", "http://purl.org/dc/elements/1.1/" },
|
{ "dc", "http://purl.org/dc/elements/1.1/" },
|
||||||
{ "dcterms", "http://purl.org/dc/terms/" },
|
{ "dcterms", "http://purl.org/dc/terms/" },
|
||||||
|
|
|
@ -43,7 +43,7 @@ std::string to_string(relationship::type t)
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
|
||||||
case relationship::type::shared_string_table:
|
case relationship::type::shared_string_table:
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
|
||||||
case relationship::type::styles:
|
case relationship::type::stylesheet:
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
||||||
case relationship::type::theme:
|
case relationship::type::theme:
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
|
||||||
|
|
|
@ -118,7 +118,7 @@ struct value_traits<xlnt::relationship_type>
|
||||||
relationship_type::shared_workbook_revision_headers,
|
relationship_type::shared_workbook_revision_headers,
|
||||||
relationship_type::shared_workbook_user_data,
|
relationship_type::shared_workbook_user_data,
|
||||||
relationship_type::single_cell_table_definitions,
|
relationship_type::single_cell_table_definitions,
|
||||||
relationship_type::styles,
|
relationship_type::stylesheet,
|
||||||
relationship_type::table_definition,
|
relationship_type::table_definition,
|
||||||
relationship_type::theme,
|
relationship_type::theme,
|
||||||
relationship_type::thumbnail,
|
relationship_type::thumbnail,
|
||||||
|
|
|
@ -36,6 +36,20 @@
|
||||||
#include <xlnt/workbook/workbook.hpp>
|
#include <xlnt/workbook/workbook.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<xml::qname>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const xml::qname& k) const
|
||||||
|
{
|
||||||
|
static std::hash<std::string> hasher;
|
||||||
|
return hasher(k.string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool is_true(const std::string &bool_string)
|
bool is_true(const std::string &bool_string)
|
||||||
|
@ -161,21 +175,34 @@ xml::parser &xlsx_consumer::parser()
|
||||||
return *parser_;
|
return *parser_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xlsx_consumer::populate_workbook()
|
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
||||||
{
|
{
|
||||||
target_.clear();
|
const auto using_namespaces = std::vector<relationship::type>
|
||||||
|
{
|
||||||
|
relationship::type::office_document,
|
||||||
|
relationship::type::stylesheet,
|
||||||
|
relationship::type::chartsheet,
|
||||||
|
relationship::type::dialogsheet,
|
||||||
|
relationship::type::worksheet
|
||||||
|
};
|
||||||
|
|
||||||
auto &manifest = target_.get_manifest();
|
auto receive = xml::parser::receive_default;
|
||||||
read_manifest();
|
auto receive_namespaces = std::find(using_namespaces.begin(), using_namespaces.end(),
|
||||||
|
rel_chain.back().get_type()) != using_namespaces.end();
|
||||||
|
|
||||||
for (const auto &rel : manifest.get_relationships(path("/")))
|
if (receive_namespaces)
|
||||||
{
|
{
|
||||||
xml::parser parser(archive_->open(rel.get_target().get_path().string()),
|
receive |= xml::parser::receive_namespace_decls;
|
||||||
rel.get_target().get_path().string());
|
}
|
||||||
parser_ = &parser;
|
|
||||||
|
|
||||||
switch (rel.get_type())
|
const auto &manifest = target_.get_manifest();
|
||||||
{
|
auto part_path = manifest.canonicalize(rel_chain);
|
||||||
|
auto &stream = archive_->open(part_path.string());
|
||||||
|
xml::parser parser(stream, part_path.string(), receive);
|
||||||
|
parser_ = &parser;
|
||||||
|
|
||||||
|
switch (rel_chain.back().get_type())
|
||||||
|
{
|
||||||
case relationship::type::core_properties:
|
case relationship::type::core_properties:
|
||||||
read_core_properties();
|
read_core_properties();
|
||||||
break;
|
break;
|
||||||
|
@ -189,7 +216,7 @@ void xlsx_consumer::populate_workbook()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::office_document:
|
case relationship::type::office_document:
|
||||||
check_document_type(manifest.get_content_type(rel.get_target().get_path()));
|
check_document_type(manifest.get_content_type(part_path));
|
||||||
read_workbook();
|
read_workbook();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -221,58 +248,11 @@ void xlsx_consumer::populate_workbook()
|
||||||
read_volatile_dependencies();
|
read_volatile_dependencies();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::thumbnail: break;
|
|
||||||
case relationship::type::calculation_chain: break;
|
|
||||||
case relationship::type::worksheet: break;
|
|
||||||
case relationship::type::shared_string_table: break;
|
|
||||||
case relationship::type::styles: break;
|
|
||||||
case relationship::type::theme: break;
|
|
||||||
case relationship::type::hyperlink: break;
|
|
||||||
case relationship::type::chartsheet: break;
|
|
||||||
case relationship::type::comments: break;
|
|
||||||
case relationship::type::vml_drawing: break;
|
|
||||||
case relationship::type::unknown: break;
|
|
||||||
case relationship::type::printer_settings: break;
|
|
||||||
case relationship::type::custom_property: break;
|
|
||||||
case relationship::type::dialogsheet: break;
|
|
||||||
case relationship::type::drawings: break;
|
|
||||||
case relationship::type::pivot_table_cache_definition: break;
|
|
||||||
case relationship::type::pivot_table_cache_records: break;
|
|
||||||
case relationship::type::query_table: break;
|
|
||||||
case relationship::type::shared_workbook: break;
|
|
||||||
case relationship::type::revision_log: break;
|
|
||||||
case relationship::type::shared_workbook_user_data: break;
|
|
||||||
case relationship::type::single_cell_table_definitions: break;
|
|
||||||
case relationship::type::table_definition: break;
|
|
||||||
case relationship::type::image: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document);
|
|
||||||
|
|
||||||
// First pass of workbook relationship parts which must be read before sheets (e.g. shared strings)
|
|
||||||
|
|
||||||
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
|
|
||||||
{
|
|
||||||
path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
|
|
||||||
auto receive = xml::parser::receive_default;
|
|
||||||
auto using_namespaces = rel.get_type() == relationship::type::styles;
|
|
||||||
if (using_namespaces)
|
|
||||||
{
|
|
||||||
receive |= xml::parser::receive_namespace_decls;
|
|
||||||
}
|
|
||||||
xml::parser parser(archive_->open(part_path.string()), part_path.string(), receive);
|
|
||||||
parser_ = &parser;
|
|
||||||
|
|
||||||
switch (rel.get_type())
|
|
||||||
{
|
|
||||||
case relationship::type::shared_string_table:
|
case relationship::type::shared_string_table:
|
||||||
read_shared_string_table();
|
read_shared_string_table();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::styles:
|
case relationship::type::stylesheet:
|
||||||
read_stylesheet();
|
read_stylesheet();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -280,108 +260,108 @@ void xlsx_consumer::populate_workbook()
|
||||||
read_theme();
|
read_theme();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::office_document: break;
|
|
||||||
case relationship::type::thumbnail: break;
|
|
||||||
case relationship::type::calculation_chain: break;
|
|
||||||
case relationship::type::extended_properties: break;
|
|
||||||
case relationship::type::core_properties: break;
|
|
||||||
case relationship::type::worksheet: break;
|
|
||||||
case relationship::type::hyperlink: break;
|
|
||||||
case relationship::type::chartsheet: break;
|
|
||||||
case relationship::type::comments: break;
|
|
||||||
case relationship::type::vml_drawing: break;
|
|
||||||
case relationship::type::unknown: break;
|
|
||||||
case relationship::type::custom_properties: break;
|
|
||||||
case relationship::type::printer_settings: break;
|
|
||||||
case relationship::type::connections: break;
|
|
||||||
case relationship::type::custom_property: break;
|
|
||||||
case relationship::type::custom_xml_mappings: break;
|
|
||||||
case relationship::type::dialogsheet: break;
|
|
||||||
case relationship::type::drawings: break;
|
|
||||||
case relationship::type::external_workbook_references: break;
|
|
||||||
case relationship::type::metadata: break;
|
|
||||||
case relationship::type::pivot_table: break;
|
|
||||||
case relationship::type::pivot_table_cache_definition: break;
|
|
||||||
case relationship::type::pivot_table_cache_records: break;
|
|
||||||
case relationship::type::query_table: break;
|
|
||||||
case relationship::type::shared_workbook_revision_headers: break;
|
|
||||||
case relationship::type::shared_workbook: break;
|
|
||||||
case relationship::type::revision_log: break;
|
|
||||||
case relationship::type::shared_workbook_user_data: break;
|
|
||||||
case relationship::type::single_cell_table_definitions: break;
|
|
||||||
case relationship::type::table_definition: break;
|
|
||||||
case relationship::type::volatile_dependencies: break;
|
|
||||||
case relationship::type::image: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second pass, read sheets themselves
|
|
||||||
|
|
||||||
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
|
|
||||||
{
|
|
||||||
path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
|
|
||||||
auto receive = xml::parser::receive_default;
|
|
||||||
receive |= xml::parser::receive_namespace_decls;
|
|
||||||
xml::parser parser(archive_->open(part_path.string()), rel.get_target().get_path().string(), receive);
|
|
||||||
parser_ = &parser;
|
|
||||||
|
|
||||||
switch (rel.get_type())
|
|
||||||
{
|
|
||||||
case relationship::type::chartsheet:
|
case relationship::type::chartsheet:
|
||||||
read_chartsheet(rel.get_id());
|
read_chartsheet(rel_chain.back().get_id());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::dialogsheet:
|
case relationship::type::dialogsheet:
|
||||||
read_dialogsheet(rel.get_id());
|
read_dialogsheet(rel_chain.back().get_id());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::worksheet:
|
case relationship::type::worksheet:
|
||||||
read_worksheet(rel.get_id());
|
read_worksheet(rel_chain.back().get_id());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::office_document: break;
|
|
||||||
case relationship::type::thumbnail: break;
|
case relationship::type::thumbnail: break;
|
||||||
case relationship::type::calculation_chain: break;
|
case relationship::type::calculation_chain: break;
|
||||||
case relationship::type::extended_properties: break;
|
|
||||||
case relationship::type::core_properties: break;
|
|
||||||
case relationship::type::shared_string_table: break;
|
|
||||||
case relationship::type::styles: break;
|
|
||||||
case relationship::type::theme: break;
|
|
||||||
case relationship::type::hyperlink: break;
|
case relationship::type::hyperlink: break;
|
||||||
case relationship::type::comments: break;
|
case relationship::type::comments: break;
|
||||||
case relationship::type::vml_drawing: break;
|
case relationship::type::vml_drawing: break;
|
||||||
case relationship::type::unknown: break;
|
case relationship::type::unknown: break;
|
||||||
case relationship::type::custom_properties: break;
|
|
||||||
case relationship::type::printer_settings: break;
|
case relationship::type::printer_settings: break;
|
||||||
case relationship::type::connections: break;
|
|
||||||
case relationship::type::custom_property: break;
|
case relationship::type::custom_property: break;
|
||||||
case relationship::type::custom_xml_mappings: break;
|
|
||||||
case relationship::type::drawings: break;
|
case relationship::type::drawings: break;
|
||||||
case relationship::type::external_workbook_references: break;
|
|
||||||
case relationship::type::metadata: break;
|
|
||||||
case relationship::type::pivot_table: break;
|
|
||||||
case relationship::type::pivot_table_cache_definition: break;
|
case relationship::type::pivot_table_cache_definition: break;
|
||||||
case relationship::type::pivot_table_cache_records: break;
|
case relationship::type::pivot_table_cache_records: break;
|
||||||
case relationship::type::query_table: break;
|
case relationship::type::query_table: break;
|
||||||
case relationship::type::shared_workbook_revision_headers: break;
|
|
||||||
case relationship::type::shared_workbook: break;
|
case relationship::type::shared_workbook: break;
|
||||||
case relationship::type::revision_log: break;
|
case relationship::type::revision_log: break;
|
||||||
case relationship::type::shared_workbook_user_data: break;
|
case relationship::type::shared_workbook_user_data: break;
|
||||||
case relationship::type::single_cell_table_definitions: break;
|
case relationship::type::single_cell_table_definitions: break;
|
||||||
case relationship::type::table_definition: break;
|
case relationship::type::table_definition: break;
|
||||||
case relationship::type::volatile_dependencies: break;
|
|
||||||
case relationship::type::image: break;
|
case relationship::type::image: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser_ = nullptr;
|
parser_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xlsx_consumer::populate_workbook()
|
||||||
|
{
|
||||||
|
target_.clear();
|
||||||
|
|
||||||
|
read_manifest();
|
||||||
|
auto &manifest = target_.get_manifest();
|
||||||
|
|
||||||
|
auto package_parts = std::vector<relationship::type>
|
||||||
|
{
|
||||||
|
relationship::type::core_properties,
|
||||||
|
relationship::type::extended_properties,
|
||||||
|
relationship::type::custom_properties,
|
||||||
|
relationship::type::office_document,
|
||||||
|
relationship::type::connections,
|
||||||
|
relationship::type::custom_xml_mappings,
|
||||||
|
relationship::type::external_workbook_references,
|
||||||
|
relationship::type::metadata,
|
||||||
|
relationship::type::pivot_table,
|
||||||
|
relationship::type::shared_workbook_revision_headers,
|
||||||
|
relationship::type::volatile_dependencies
|
||||||
|
};
|
||||||
|
|
||||||
|
auto root_path = path("/");
|
||||||
|
|
||||||
|
for (auto rel_type : package_parts)
|
||||||
|
{
|
||||||
|
if (manifest.has_relationship(root_path, rel_type))
|
||||||
|
{
|
||||||
|
read_part({ manifest.get_relationship(root_path, rel_type) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown Parts
|
const auto workbook_rel = manifest.get_relationship(root_path,
|
||||||
|
relationship::type::office_document);
|
||||||
|
|
||||||
void read_unknown_parts();
|
const auto workbook_parts_first = std::vector<relationship::type>
|
||||||
void read_unknown_relationships();
|
{
|
||||||
|
relationship::type::shared_string_table,
|
||||||
|
relationship::type::stylesheet,
|
||||||
|
relationship::type::theme
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto rel_type : workbook_parts_first)
|
||||||
|
{
|
||||||
|
if (manifest.has_relationship(workbook_rel.get_target().get_path(), rel_type))
|
||||||
|
{
|
||||||
|
read_part({ workbook_rel, manifest.get_relationship(workbook_rel.get_target().get_path(), rel_type) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto workbook_parts_second = std::vector<relationship::type>
|
||||||
|
{
|
||||||
|
relationship::type::worksheet,
|
||||||
|
relationship::type::chartsheet,
|
||||||
|
relationship::type::dialogsheet
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto rel_type : workbook_parts_second)
|
||||||
|
{
|
||||||
|
if (manifest.has_relationship(workbook_rel.get_target().get_path(), rel_type))
|
||||||
|
{
|
||||||
|
for (auto rel : manifest.get_relationships(workbook_rel.get_target().get_path(), rel_type))
|
||||||
|
{
|
||||||
|
read_part({ workbook_rel, rel });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package Parts
|
// Package Parts
|
||||||
|
@ -467,80 +447,128 @@ void xlsx_consumer::read_extended_properties()
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties");
|
parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties");
|
||||||
parser().content(xml::parser::content_type::complex);
|
parser().content(xml::parser::content_type::complex);
|
||||||
|
|
||||||
while (true)
|
read_block(
|
||||||
{
|
{
|
||||||
if (parser().peek() == xml::parser::event_type::end_element) break;
|
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element);
|
|
||||||
|
|
||||||
auto name = parser().name();
|
|
||||||
auto text = std::string();
|
|
||||||
|
|
||||||
while (parser().peek() == xml::parser::event_type::characters)
|
|
||||||
{
|
{
|
||||||
parser().next_expect(xml::parser::event_type::characters);
|
xml::qname(xmlns, "Application"),
|
||||||
text.append(parser().value());
|
[](xlsx_consumer &c)
|
||||||
}
|
|
||||||
|
|
||||||
if (name == "Application") target_.set_application(text);
|
|
||||||
else if (name == "DocSecurity") target_.set_doc_security(std::stoi(text));
|
|
||||||
else if (name == "ScaleCrop") target_.set_scale_crop(is_true(text));
|
|
||||||
else if (name == "Company") target_.set_company(text);
|
|
||||||
else if (name == "SharedDoc") target_.set_shared_doc(is_true(text));
|
|
||||||
else if (name == "HyperlinksChanged") target_.set_hyperlinks_changed(is_true(text));
|
|
||||||
else if (name == "AppVersion") target_.set_app_version(text);
|
|
||||||
else if (name == "Application") target_.set_application(text);
|
|
||||||
else if (name == "HeadingPairs")
|
|
||||||
{
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
|
||||||
parser().content(xml::parser::content_type::complex);
|
|
||||||
|
|
||||||
parser().attribute("size");
|
|
||||||
parser().attribute("baseType");
|
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
|
||||||
parser().content(xml::parser::content_type::complex);
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
|
||||||
parser().next_expect(xml::parser::event_type::characters);
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
|
||||||
parser().content(xml::parser::content_type::complex);
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "i4");
|
|
||||||
parser().next_expect(xml::parser::event_type::characters);
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "i4");
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
|
||||||
}
|
|
||||||
else if (name == "TitlesOfParts")
|
|
||||||
{
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
|
||||||
parser().content(xml::parser::content_type::complex);
|
|
||||||
|
|
||||||
parser().attribute("size");
|
|
||||||
parser().attribute("baseType");
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
if (parser().peek() == xml::parser::event_type::end_element) break;
|
c.target_.set_application(c.read_text());
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
|
||||||
parser().content(xml::parser::content_type::simple);
|
|
||||||
parser().next_expect(xml::parser::event_type::characters);
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (parser().peek() == xml::parser::event_type::characters)
|
|
||||||
{
|
{
|
||||||
parser().next_expect(xml::parser::event_type::characters);
|
xml::qname(xmlns, "DocSecurity"),
|
||||||
}
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_doc_security(std::stoi(c.read_text()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "ScaleCrop"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_scale_crop(is_true(c.read_text()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "Company"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_company(c.read_text());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "SharedDoc"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_shared_doc(is_true(c.read_text()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "HyperlinksChanged"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_hyperlinks_changed(is_true(c.read_text()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "AppVersion"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_app_version(c.read_text());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "LinksUpToDate"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.target_.set_links_up_to_date(is_true(c.read_text()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "Template"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.read_text();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "TotalTime"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.read_text();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "HeadingPairs"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element);
|
c.parser().attribute("size");
|
||||||
}
|
c.parser().attribute("baseType");
|
||||||
|
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
||||||
|
c.parser().next_expect(xml::parser::event_type::characters);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "variant");
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "i4");
|
||||||
|
c.parser().next_expect(xml::parser::event_type::characters);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "i4");
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "variant");
|
||||||
|
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xml::qname(xmlns, "TitlesOfParts"),
|
||||||
|
[](xlsx_consumer &c)
|
||||||
|
{
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "vector");
|
||||||
|
c.parser().content(xml::parser::content_type::complex);
|
||||||
|
|
||||||
|
auto size = c.parser().attribute<std::size_t>("size");
|
||||||
|
c.parser().attribute("baseType");
|
||||||
|
|
||||||
|
for (auto i = std::size_t(0); i < size; ++i)
|
||||||
|
{
|
||||||
|
c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr");
|
||||||
|
c.parser().content(xml::parser::content_type::simple);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::characters);
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "lpstr");
|
||||||
|
}
|
||||||
|
|
||||||
|
c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void xlsx_consumer::read_core_properties()
|
void xlsx_consumer::read_core_properties()
|
||||||
|
@ -613,8 +641,11 @@ void xlsx_consumer::read_workbook()
|
||||||
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
||||||
{
|
{
|
||||||
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
||||||
if (parser().name() == "x15") target_.enable_x15();
|
|
||||||
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
if (parser().namespace_() == xmlns_x15)
|
||||||
|
{
|
||||||
|
target_.enable_x15();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable")))
|
if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable")))
|
||||||
|
@ -624,7 +655,8 @@ void xlsx_consumer::read_workbook()
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (parser().peek() == xml::parser::event_type::end_element) break;
|
if (parser().peek() == xml::parser::event_type::end_element
|
||||||
|
|| parser().peek() == xml::parser::event_type::end_namespace_decl) break;
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element);
|
parser().next_expect(xml::parser::event_type::start_element);
|
||||||
parser().content(xml::parser::content_type::complex);
|
parser().content(xml::parser::content_type::complex);
|
||||||
|
@ -652,14 +684,31 @@ void xlsx_consumer::read_workbook()
|
||||||
}
|
}
|
||||||
else if (qname == xml::qname(xmlns_mc, "AlternateContent"))
|
else if (qname == xml::qname(xmlns_mc, "AlternateContent"))
|
||||||
{
|
{
|
||||||
|
if (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
||||||
|
{
|
||||||
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
||||||
|
}
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_mc, "Choice");
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_mc, "Choice");
|
||||||
parser().content(xml::parser::content_type::complex);
|
parser().content(xml::parser::content_type::complex);
|
||||||
parser().attribute("Requires");
|
parser().attribute("Requires");
|
||||||
parser().next_expect(xml::parser::event_type::start_element, xmlns_x15ac, "absPath");
|
parser().next_expect(xml::parser::event_type::start_element, xmlns_x15ac, "absPath");
|
||||||
target_.set_absolute_path(path(parser().attribute("url")));
|
target_.set_absolute_path(path(parser().attribute("url")));
|
||||||
|
|
||||||
|
if (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
||||||
|
{
|
||||||
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
||||||
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
||||||
|
}
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_x15ac, "absPath");
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_x15ac, "absPath");
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "Choice");
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "Choice");
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "AlternateContent");
|
parser().next_expect(xml::parser::event_type::end_element, xmlns_mc, "AlternateContent");
|
||||||
|
|
||||||
|
if (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
||||||
|
{
|
||||||
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (qname == xml::qname(xmlns, "bookViews"))
|
else if (qname == xml::qname(xmlns, "bookViews"))
|
||||||
{
|
{
|
||||||
|
@ -821,6 +870,7 @@ void xlsx_consumer::read_workbook()
|
||||||
{
|
{
|
||||||
if (parser().peek() == xml::parser::event_type::end_element) break;
|
if (parser().peek() == xml::parser::event_type::end_element) break;
|
||||||
|
|
||||||
|
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
||||||
parser().next_expect(xml::parser::event_type::start_element);
|
parser().next_expect(xml::parser::event_type::start_element);
|
||||||
|
|
||||||
if (parser().qname() == xml::qname(xmlns_mx, "ArchID"))
|
if (parser().qname() == xml::qname(xmlns_mx, "ArchID"))
|
||||||
|
@ -842,6 +892,7 @@ void xlsx_consumer::read_workbook()
|
||||||
}
|
}
|
||||||
|
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext");
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext");
|
||||||
|
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
||||||
parser().next_expect(xml::parser::event_type::end_element, xmlns, "extLst");
|
parser().next_expect(xml::parser::event_type::end_element, xmlns, "extLst");
|
||||||
}
|
}
|
||||||
else if (qname == xml::qname(xmlns, "workbookProtection"))
|
else if (qname == xml::qname(xmlns, "workbookProtection"))
|
||||||
|
@ -2302,5 +2353,40 @@ void xlsx_consumer::read_unknown_relationships()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string xlsx_consumer::read_text()
|
||||||
|
{
|
||||||
|
auto text = std::string();
|
||||||
|
|
||||||
|
while (parser().peek() == xml::parser::event_type::characters)
|
||||||
|
{
|
||||||
|
parser().next_expect(xml::parser::event_type::characters);
|
||||||
|
text.append(parser().value());
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xlsx_consumer::read_block(const std::unordered_map<xml::qname, std::function<void(xlsx_consumer &)>> &handlers)
|
||||||
|
{
|
||||||
|
auto parent_block = parser().qname();
|
||||||
|
|
||||||
|
while (parser().peek() != xml::parser::event_type::end_element)
|
||||||
|
{
|
||||||
|
parser().next_expect(xml::parser::event_type::start_element);
|
||||||
|
auto block = parser().qname();
|
||||||
|
|
||||||
|
if (handlers.count(block) == 0)
|
||||||
|
{
|
||||||
|
throw xlnt::key_not_found();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &handler = handlers.at(block);
|
||||||
|
handler(*this);
|
||||||
|
parser().next_expect(xml::parser::event_type::end_element, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
parser().next_expect(xml::parser::event_type::end_element, parent_block);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namepsace xlnt
|
} // namepsace xlnt
|
||||||
|
|
|
@ -219,6 +219,12 @@ private:
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void read_unknown_relationships();
|
void read_unknown_relationships();
|
||||||
|
|
||||||
|
std::string read_text();
|
||||||
|
|
||||||
|
void read_block(const std::unordered_map<xml::qname, std::function<void(xlsx_consumer &)>> &handlers);
|
||||||
|
|
||||||
|
void read_part(const std::vector<relationship> &rel_chain);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ZIP file containing the files that make up the OOXML package.
|
/// The ZIP file containing the files that make up the OOXML package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -133,7 +133,7 @@ void xlsx_producer::populate_archive()
|
||||||
case relationship::type::calculation_chain: break;
|
case relationship::type::calculation_chain: break;
|
||||||
case relationship::type::worksheet: break;
|
case relationship::type::worksheet: break;
|
||||||
case relationship::type::shared_string_table: break;
|
case relationship::type::shared_string_table: break;
|
||||||
case relationship::type::styles: break;
|
case relationship::type::stylesheet: break;
|
||||||
case relationship::type::theme: break;
|
case relationship::type::theme: break;
|
||||||
case relationship::type::hyperlink: break;
|
case relationship::type::hyperlink: break;
|
||||||
case relationship::type::chartsheet: break;
|
case relationship::type::chartsheet: break;
|
||||||
|
@ -408,8 +408,8 @@ void xlsx_producer::write_workbook(const relationship &rel)
|
||||||
serializer().start_element(xmlns_x15ac, "absPath");
|
serializer().start_element(xmlns_x15ac, "absPath");
|
||||||
serializer().namespace_decl(xmlns_x15ac, "x15ac");
|
serializer().namespace_decl(xmlns_x15ac, "x15ac");
|
||||||
serializer().attribute("url", source_.get_absolute_path().string());
|
serializer().attribute("url", source_.get_absolute_path().string());
|
||||||
|
|
||||||
serializer().end_element(xmlns_x15ac, "absPath");
|
serializer().end_element(xmlns_x15ac, "absPath");
|
||||||
|
|
||||||
serializer().end_element(xmlns_mc, "Choice");
|
serializer().end_element(xmlns_mc, "Choice");
|
||||||
serializer().end_element(xmlns_mc, "AlternateContent");
|
serializer().end_element(xmlns_mc, "AlternateContent");
|
||||||
}
|
}
|
||||||
|
@ -586,7 +586,7 @@ void xlsx_producer::write_workbook(const relationship &rel)
|
||||||
write_shared_workbook_revision_headers(child_rel);
|
write_shared_workbook_revision_headers(child_rel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relationship::type::styles:
|
case relationship::type::stylesheet:
|
||||||
write_styles(child_rel);
|
write_styles(child_rel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2364,7 +2364,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
|
||||||
case relationship::type::core_properties: break;
|
case relationship::type::core_properties: break;
|
||||||
case relationship::type::worksheet: break;
|
case relationship::type::worksheet: break;
|
||||||
case relationship::type::shared_string_table: break;
|
case relationship::type::shared_string_table: break;
|
||||||
case relationship::type::styles: break;
|
case relationship::type::stylesheet: break;
|
||||||
case relationship::type::theme: break;
|
case relationship::type::theme: break;
|
||||||
case relationship::type::hyperlink: break;
|
case relationship::type::hyperlink: break;
|
||||||
case relationship::type::chartsheet: break;
|
case relationship::type::chartsheet: break;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void manifest::clear()
|
||||||
relationships_.clear();
|
relationships_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
path manifest::canonicalize(const std::vector<relationship> &rels)
|
path manifest::canonicalize(const std::vector<relationship> &rels) const
|
||||||
{
|
{
|
||||||
xlnt::path relative;
|
xlnt::path relative;
|
||||||
|
|
||||||
|
|
|
@ -450,12 +450,12 @@ void workbook::register_stylesheet_in_manifest()
|
||||||
{
|
{
|
||||||
auto wb_rel = get_manifest().get_relationship(path("/"), relationship_type::office_document);
|
auto wb_rel = get_manifest().get_relationship(path("/"), relationship_type::office_document);
|
||||||
|
|
||||||
if (!get_manifest().has_relationship(wb_rel.get_target().get_path(), relationship_type::styles))
|
if (!get_manifest().has_relationship(wb_rel.get_target().get_path(), relationship_type::stylesheet))
|
||||||
{
|
{
|
||||||
get_manifest().register_override_type(constants::part_styles(),
|
get_manifest().register_override_type(constants::part_styles(),
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
|
||||||
get_manifest().register_relationship(wb_rel.get_target(),
|
get_manifest().register_relationship(wb_rel.get_target(),
|
||||||
relationship::type::styles, uri("styles.xml"), target_mode::internal);
|
relationship::type::stylesheet, uri("styles.xml"), target_mode::internal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user