mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
improve manifest interface, work on round-tripping
This commit is contained in:
parent
ed591e1559
commit
1b5bdbeb18
|
@ -32,42 +32,6 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
enum class content_type
|
||||
{
|
||||
core_properties,
|
||||
extended_properties,
|
||||
custom_properties,
|
||||
|
||||
calculation_chain,
|
||||
chartsheet,
|
||||
comments,
|
||||
connections,
|
||||
custom_property,
|
||||
custom_xml_mappings,
|
||||
dialogsheet,
|
||||
drawings,
|
||||
external_workbook_references,
|
||||
metadata,
|
||||
pivot_table,
|
||||
pivot_table_cache_definition,
|
||||
pivot_table_cache_records,
|
||||
query_table,
|
||||
shared_string_table,
|
||||
shared_workbook_revision_headers,
|
||||
shared_workbook,
|
||||
revision_log,
|
||||
shared_workbook_user_data,
|
||||
single_cell_table_definitions,
|
||||
styles,
|
||||
table_definition,
|
||||
theme,
|
||||
volatile_dependencies,
|
||||
workbook,
|
||||
worksheet,
|
||||
|
||||
unknown
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The manifest keeps track of all files in the OOXML package and
|
||||
/// their type and relationships.
|
||||
|
@ -76,121 +40,68 @@ class XLNT_CLASS manifest
|
|||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Convenience method for clear_types() and clear_relationships()
|
||||
/// Unregisters all default and override type and all relationships and known parts.
|
||||
/// </summary>
|
||||
void clear();
|
||||
|
||||
/// <summary>
|
||||
/// Convenince method for clear_default_types() and clear_override_types()
|
||||
/// Returns the path to all internal package parts registered as a source
|
||||
/// or target of a relationship.
|
||||
/// </summary>
|
||||
void clear_types();
|
||||
std::vector<path> get_parts() const;
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters every default content type (i.e. type based on part extension).
|
||||
/// </summary>
|
||||
void clear_default_types();
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters every content type for every part except default types.
|
||||
/// </summary>
|
||||
void clear_override_types();
|
||||
|
||||
/// <summary>
|
||||
/// Convenince method for clear_package_relationships() and clear_part_relationships()
|
||||
/// </summary>
|
||||
void clear_relationships();
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters every relationship with the package root as the source.
|
||||
/// </summary>
|
||||
void clear_package_relationships();
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters every relationship except those with the package root as the source.
|
||||
/// </summary>
|
||||
void clear_part_relationships();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the manifest contains a package relationship with the given type.
|
||||
/// </summary>
|
||||
bool has_package_relationship(relationship::type type) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the manifest contains a package relationship with the given id.
|
||||
/// </summary>
|
||||
bool has_package_relationship(const std::string &rel_id) const;
|
||||
// Relationships
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the manifest contains a relationship with the given type with part as the source.
|
||||
/// </summary>
|
||||
bool has_part_relationship(const path &part, relationship::type type) const;
|
||||
bool has_relationship(const path &source, relationship::type type) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the manifest contains a relationship with the given type with part as the source.
|
||||
/// </summary>
|
||||
bool has_part_relationship(const path &part, const std::string &rel_id) const;
|
||||
|
||||
relationship get_package_relationship(relationship::type type) const;
|
||||
|
||||
relationship get_package_relationship(const std::string &rel_id) const;
|
||||
|
||||
std::vector<relationship> get_package_relationships() const;
|
||||
|
||||
std::vector<relationship> get_package_relationships(relationship::type type) const;
|
||||
|
||||
relationship get_part_relationship(const path &part, relationship::type type) const;
|
||||
|
||||
relationship get_part_relationship(const path &part, const std::string &rel_id) const;
|
||||
|
||||
std::vector<relationship> get_part_relationships(const path &part) const;
|
||||
|
||||
std::vector<relationship> get_part_relationships(const path &part, relationship::type type) const;
|
||||
bool has_relationship(const path &source, const std::string &rel_id) const;
|
||||
|
||||
/// <summary>
|
||||
/// Given the path to a part, returns the content type of the part as
|
||||
/// a content_type enum value or content_type::unknown if it isn't known.
|
||||
/// Returns the relationship with "source" as the source and with a type of "type".
|
||||
/// Throws a key_not_found exception if no such relationship is found.
|
||||
/// </summary>
|
||||
content_type get_content_type(const path &part) const;
|
||||
relationship get_relationship(const path &source, relationship::type type) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the relationship with "source" as the source and with an ID of "rel_id".
|
||||
/// Throws a key_not_found exception if no such relationship is found.
|
||||
/// </summary>
|
||||
relationship get_relationship(const path &source, const std::string &rel_id) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all relationship with "source" as the source.
|
||||
/// </summary>
|
||||
std::vector<relationship> get_relationships(const path &source) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all relationships with "source" as the source and with a type of "type".
|
||||
/// </summary>
|
||||
std::vector<relationship> get_relationships(const path &source, relationship::type type) const;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_relationship(const uri &source, relationship::type type, const uri &target, target_mode mode);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_relationship(const uri &source, relationship::type type, const uri &target, target_mode mode, const std::string &rel_id);
|
||||
|
||||
// Content Types
|
||||
|
||||
/// <summary>
|
||||
/// Given the path to a part, returns the content type of the part as a string.
|
||||
/// </summary>
|
||||
std::string get_content_type_string(const path &part) const;
|
||||
std::string get_content_type(const path &part) const;
|
||||
|
||||
void register_override_type(const path &part, const std::string &content_type);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the path of the part of the given type and removes all relationships
|
||||
/// with the part as a source or target.
|
||||
/// </summary>
|
||||
void unregister_override_type(const path &part);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the part at the given path has been registered in this manifest.
|
||||
/// </summary>
|
||||
bool has_override_type(const path &part) const;
|
||||
|
||||
std::vector<path> get_overriden_parts() const;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_package_relationship(relationship::type type, const path &target_uri, target_mode mode);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_package_relationship(relationship::type type, const path &target_uri, target_mode mode, const std::string &rel_id);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_part_relationship(const path &source_uri, relationship::type type, const path &target_uri, target_mode mode);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
std::string register_part_relationship(const path &source_uri, relationship::type type, const path &target_uri, target_mode mode, const std::string &rel_id);
|
||||
// Default Content Types
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a default content type for the extension has been registered.
|
||||
|
@ -200,9 +111,7 @@ public:
|
|||
/// <summary>
|
||||
/// Returns a vector of all extensions with registered default content types.
|
||||
/// </summary>
|
||||
std::vector<std::string> get_default_type_extensions() const;
|
||||
|
||||
std::vector<path> get_parts_with_relationships() const;
|
||||
std::vector<std::string> get_extensions_with_default_types() const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the registered default content type for parts of the given extension.
|
||||
|
@ -212,29 +121,50 @@ public:
|
|||
/// <summary>
|
||||
/// Associates the given extension with the given content type.
|
||||
/// </summary>
|
||||
void register_default_type(const std::string &extension, const std::string &content_type);
|
||||
void register_default_type(const std::string &extension, const std::string &type);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the default content type for the given extension.
|
||||
/// </summary>
|
||||
void unregister_default_type(const std::string &extension);
|
||||
|
||||
// Override Content Types
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a content type overriding the default content type has been registered
|
||||
/// for the given part.
|
||||
/// </summary>
|
||||
bool has_override_type(const path &part) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the override content type registered for the given part.
|
||||
/// Throws key_not_found exception if no override type was found.
|
||||
/// </summary>
|
||||
std::string get_override_type(const path &part) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the path of every part in this manifest with an overriden content type.
|
||||
/// </summary>
|
||||
std::vector<path> get_parts_with_overriden_types() const;
|
||||
|
||||
/// <summary>
|
||||
/// Overrides any default type registered for the part's extension with the given content type.
|
||||
/// </summary>
|
||||
void register_override_type(const path &part, const std::string &type);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the overriding content type of the given part.
|
||||
/// </summary>
|
||||
void unregister_override_type(const path &part);
|
||||
|
||||
private:
|
||||
struct part_info
|
||||
{
|
||||
std::string content_type;
|
||||
std::vector<relationship> relationships;
|
||||
};
|
||||
|
||||
std::string next_package_relationship_id() const;
|
||||
|
||||
std::string next_relationship_id(const path &part) const;
|
||||
|
||||
std::unordered_map<path, part_info> part_infos_;
|
||||
std::unordered_map<std::string, std::string> default_content_types_;
|
||||
|
||||
std::vector<relationship> package_relationships_;
|
||||
std::unordered_map<path, std::string> override_content_types_;
|
||||
|
||||
std::unordered_map<std::string, std::string> extension_content_type_map_;
|
||||
std::unordered_map<path, std::unordered_map<std::string, relationship>> relationships_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
uri make_absolute(const uri &base);
|
||||
uri make_reference(const uri &base);
|
||||
|
||||
friend XLNT_FUNCTION bool operator==(const uri &left, const uri &right);
|
||||
|
||||
private:
|
||||
bool absolute_;
|
||||
std::string scheme_;
|
||||
|
|
|
@ -104,8 +104,10 @@ protected:
|
|||
|
||||
private:
|
||||
std::unordered_map<side, border_property> sides_;
|
||||
/*
|
||||
bool outline_ = true;
|
||||
diagonal_direction diagonal_direction_ = diagonal_direction::neither;
|
||||
*/
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -155,6 +155,8 @@ public:
|
|||
/// </summary>
|
||||
path append(const path &to_append) const;
|
||||
|
||||
friend XLNT_FUNCTION bool operator==(const path &left, const path &right);
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Returns the character that separates directories in the path.
|
||||
|
|
|
@ -71,9 +71,9 @@ struct workbook_impl
|
|||
guess_types_(other.guess_types_),
|
||||
data_only_(other.data_only_),
|
||||
stylesheet_(other.stylesheet_),
|
||||
manifest_(other.manifest_),
|
||||
has_theme_(other.has_theme_),
|
||||
theme_(other.theme_),
|
||||
manifest_(other.manifest_),
|
||||
write_core_properties_(other.write_core_properties_),
|
||||
creator_(other.creator_),
|
||||
last_modified_by_(other.last_modified_by_),
|
||||
|
|
|
@ -19,11 +19,6 @@ bool is_true(const std::string &bool_string)
|
|||
return bool_string == "1" || bool_string == "true";
|
||||
}
|
||||
|
||||
bool is_false(const std::string &bool_string)
|
||||
{
|
||||
return bool_string == "0" || bool_string == "false";
|
||||
}
|
||||
|
||||
std::size_t string_to_size_t(const std::string &s)
|
||||
{
|
||||
#if ULLONG_MAX == SIZE_MAX
|
||||
|
@ -59,16 +54,6 @@ struct EnumClassHash
|
|||
}
|
||||
};
|
||||
|
||||
std::string string_lower(std::string str)
|
||||
{
|
||||
for (std::size_t i = 0; i < str.size(); i++)
|
||||
{
|
||||
str[i] = std::tolower(str[i]);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T from_string(const std::string &string);
|
||||
|
||||
|
@ -649,45 +634,21 @@ std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt:
|
|||
document.load_string(archive.read(part).c_str());
|
||||
|
||||
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::path rel_target(relationship_node.attribute("Target").value());
|
||||
xlnt::uri target(relationship_node.attribute("Target").value());
|
||||
|
||||
relationships.push_back(xlnt::relationship(id, type, rel_target, xlnt::target_mode::internal));
|
||||
relationships.push_back(xlnt::relationship(id, type, source, target, xlnt::target_mode::internal));
|
||||
}
|
||||
|
||||
return relationships;
|
||||
}
|
||||
|
||||
std::string::size_type find_string_in_string(const std::string &string, const std::string &substring)
|
||||
{
|
||||
std::string::size_type possible_match_index = string.find(substring.at(0));
|
||||
|
||||
while (possible_match_index != std::string::npos)
|
||||
{
|
||||
if (string.substr(possible_match_index, substring.size()) == substring)
|
||||
{
|
||||
return possible_match_index;
|
||||
}
|
||||
|
||||
possible_match_index = string.find(substring.at(0), possible_match_index + 1);
|
||||
}
|
||||
|
||||
return possible_match_index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if d is exactly equal to an integer.
|
||||
/// </summary>
|
||||
bool is_integral(long double d)
|
||||
{
|
||||
return d == static_cast<long long int>(d);
|
||||
}
|
||||
|
||||
void check_document_type(const std::string &document_content_type)
|
||||
{
|
||||
if (document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
|
||||
|
@ -733,12 +694,11 @@ void xlsx_consumer::populate_workbook()
|
|||
{
|
||||
auto &manifest = destination_.get_manifest();
|
||||
read_manifest();
|
||||
path workbook_part;
|
||||
|
||||
for (const auto &rel : manifest.get_package_relationships())
|
||||
for (const auto &rel : manifest.get_relationships(path("/")))
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path(rel.get_target_uri())).c_str());
|
||||
document.load_string(source_.read(rel.get_target().get_path()).c_str());
|
||||
|
||||
switch (rel.get_type())
|
||||
{
|
||||
|
@ -752,20 +712,9 @@ void xlsx_consumer::populate_workbook()
|
|||
read_custom_property(document.root());
|
||||
break;
|
||||
case relationship::type::office_document:
|
||||
check_document_type(manifest.get_content_type_string(rel.get_target_uri()));
|
||||
workbook_part = rel.get_target_uri();
|
||||
check_document_type(manifest.get_content_type(rel.get_target().get_path()));
|
||||
read_workbook(document.root());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &rel : manifest.get_part_relationships(workbook_part))
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path(rel.get_target_uri())).c_str());
|
||||
|
||||
switch (rel.get_type())
|
||||
{
|
||||
case relationship::type::calculation_chain:
|
||||
read_calculation_chain(document.root());
|
||||
break;
|
||||
|
@ -799,13 +748,17 @@ void xlsx_consumer::populate_workbook()
|
|||
case relationship::type::volatile_dependencies:
|
||||
read_volatile_dependencies(document.root());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &rel : manifest.get_part_relationships(workbook_part))
|
||||
const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document);
|
||||
|
||||
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path(rel.get_target_uri())).c_str());
|
||||
document.load_string(source_.read(path(rel.get_target().get_path())).c_str());
|
||||
|
||||
switch (rel.get_type())
|
||||
{
|
||||
|
@ -818,6 +771,8 @@ void xlsx_consumer::populate_workbook()
|
|||
case relationship::type::worksheet:
|
||||
read_worksheet(document.root(), rel.get_id());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -846,18 +801,6 @@ void xlsx_consumer::read_manifest()
|
|||
const auto root_node = document.child("Types");
|
||||
auto &manifest = destination_.get_manifest();
|
||||
|
||||
auto make_relative = [](const path &p)
|
||||
{
|
||||
path copy;
|
||||
|
||||
for (const auto &part : std::vector<std::string>(p.begin() + 1, p.end()))
|
||||
{
|
||||
copy.append(part);
|
||||
}
|
||||
|
||||
return copy;
|
||||
};
|
||||
|
||||
for (const auto child : root_node.children())
|
||||
{
|
||||
if (child.name() == std::string("Default"))
|
||||
|
@ -874,8 +817,9 @@ void xlsx_consumer::read_manifest()
|
|||
|
||||
for (const auto &package_rel : package_rels)
|
||||
{
|
||||
manifest.register_package_relationship(package_rel.get_type(),
|
||||
package_rel.get_target_uri(),
|
||||
manifest.register_relationship(uri("/"),
|
||||
package_rel.get_type(),
|
||||
package_rel.get_target(),
|
||||
package_rel.get_target_mode(),
|
||||
package_rel.get_id());
|
||||
}
|
||||
|
@ -886,14 +830,13 @@ void xlsx_consumer::read_manifest()
|
|||
|| relationship_source.filename.extension() != ".rels") continue;
|
||||
|
||||
auto part_rels = read_relationships(relationship_source.filename, source_);
|
||||
auto source_uri = relationship_source.filename.parent().parent()
|
||||
.append(relationship_source.filename.basename());
|
||||
uri source(relationship_source.filename.parent().parent()
|
||||
.append(relationship_source.filename.filename()).string());
|
||||
|
||||
for (const auto part_rel : part_rels)
|
||||
{
|
||||
auto part = source_uri;
|
||||
manifest.register_part_relationship(source_uri, part_rel.get_type(),
|
||||
part_rel.get_target_uri(), part_rel.get_target_mode(), part_rel.get_id());
|
||||
manifest.register_relationship(source, part_rel.get_type(),
|
||||
part_rel.get_target(), part_rel.get_target_mode(), part_rel.get_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -934,7 +877,7 @@ void xlsx_consumer::read_custom_file_properties(const pugi::xml_node root)
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("customFileProperties");
|
||||
/*auto root_node = */document.append_child("customFileProperties");
|
||||
}
|
||||
|
||||
// Write SpreadsheetML-Specific Package Parts
|
||||
|
@ -977,56 +920,56 @@ void xlsx_consumer::read_chartsheet(const pugi::xml_node root, const std::string
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("chartsheet");
|
||||
/*auto root_node = */ document.append_child("chartsheet");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_connections(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("connections");
|
||||
/*auto root_node = */ document.append_child("connections");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_custom_property(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("customProperty");
|
||||
/*auto root_node = */ document.append_child("customProperty");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_custom_xml_mappings(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("connections");
|
||||
/*auto root_node = */ document.append_child("connections");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_dialogsheet(const pugi::xml_node root, const std::string &title)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("dialogsheet");
|
||||
/*auto root_node = */ document.append_child("dialogsheet");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_external_workbook_references(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("externalLink");
|
||||
/*auto root_node = */ document.append_child("externalLink");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_metadata(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("metadata");
|
||||
/*auto root_node = */ document.append_child("metadata");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_pivot_table(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("pivotTableDefinition");
|
||||
/*auto root_node = */ document.append_child("pivotTableDefinition");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_shared_string_table(const pugi::xml_node root)
|
||||
|
@ -1109,21 +1052,21 @@ void xlsx_consumer::read_shared_workbook_revision_headers(const pugi::xml_node r
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("headers");
|
||||
/*auto root_node = */ document.append_child("headers");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_shared_workbook(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("revisions");
|
||||
/*auto root_node = */ document.append_child("revisions");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_shared_workbook_user_data(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("users");
|
||||
/*auto root_node = */ document.append_child("users");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
|
||||
|
@ -1150,7 +1093,7 @@ void xlsx_consumer::read_volatile_dependencies(const pugi::xml_node root)
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("volTypes");
|
||||
/*auto root_node = */ document.append_child("volTypes");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_worksheet(const pugi::xml_node root, const std::string &rel_id)
|
||||
|
@ -1344,14 +1287,14 @@ void xlsx_consumer::read_comments(const pugi::xml_node root)
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("comments");
|
||||
/*auto root_node = */ document.append_child("comments");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_drawings(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("wsDr");
|
||||
/*auto root_node = */ document.append_child("wsDr");
|
||||
}
|
||||
|
||||
// Unknown Parts
|
||||
|
@ -1360,14 +1303,14 @@ void xlsx_consumer::read_unknown_parts(const pugi::xml_node root)
|
|||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("Hmm");
|
||||
/*auto root_node = */ document.append_child("Hmm");
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_unknown_relationships(const pugi::xml_node root)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load_string(source_.read(path("[Content Types].xml")).c_str());
|
||||
auto root_node = document.append_child("Relationships");
|
||||
/*auto root_node = */ document.append_child("Relationships");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -191,7 +191,7 @@ void write_relationships(const std::vector<xlnt::relationship> &relationships, p
|
|||
|
||||
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_uri().to_string('/').c_str());
|
||||
relationship_node.append_attribute("Target").set_value(relationship.get_target().get_path().string().c_str());
|
||||
|
||||
if (relationship.get_target_mode() == xlnt::target_mode::external)
|
||||
{
|
||||
|
@ -586,90 +586,43 @@ void xlsx_producer::write(std::vector<std::uint8_t> &destination)
|
|||
void xlsx_producer::populate_archive()
|
||||
{
|
||||
write_manifest();
|
||||
path workbook_part;
|
||||
|
||||
for (auto &rel : source_.impl().manifest_.get_package_relationships())
|
||||
for (auto &rel : source_.impl().manifest_.get_relationships(path("/")))
|
||||
{
|
||||
pugi::xml_document document;
|
||||
bool write_document = true;
|
||||
|
||||
switch (rel.get_type())
|
||||
{
|
||||
case relationship::type::core_properties:
|
||||
write_core_properties(document.root());
|
||||
write_core_properties(rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::extended_properties:
|
||||
write_extended_properties(document.root());
|
||||
write_extended_properties(rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::custom_properties:
|
||||
write_custom_properties(document.root());
|
||||
write_custom_properties(rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::office_document:
|
||||
write_workbook(document.root());
|
||||
workbook_part = rel.get_target_uri();
|
||||
write_workbook(rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::thumbnail:
|
||||
destination_.write_string(
|
||||
std::string(source_.get_thumbnail().begin(), source_.get_thumbnail().end()),
|
||||
rel.get_target_uri());
|
||||
continue;
|
||||
write_thumbnail(rel);
|
||||
write_document = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
write_document_to_archive(document, rel.get_target_uri(), destination_);
|
||||
}
|
||||
|
||||
for (auto rel : source_.impl().manifest_.get_part_relationships(workbook_part))
|
||||
if (write_document)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
|
||||
switch (rel.get_type())
|
||||
{
|
||||
case relationship::type::calculation_chain:
|
||||
write_calculation_chain(document.root());
|
||||
break;
|
||||
case relationship::type::chartsheet:
|
||||
write_chartsheet(document.root(), rel);
|
||||
break;
|
||||
case relationship::type::connections:
|
||||
write_connections(document.root());
|
||||
break;
|
||||
case relationship::type::custom_xml_mappings:
|
||||
write_custom_xml_mappings(document.root());
|
||||
break;
|
||||
case relationship::type::dialogsheet:
|
||||
write_dialogsheet(document.root(), rel);
|
||||
break;
|
||||
case relationship::type::external_workbook_references:
|
||||
write_external_workbook_references(document.root());
|
||||
break;
|
||||
case relationship::type::metadata:
|
||||
write_metadata(document.root());
|
||||
break;
|
||||
case relationship::type::pivot_table:
|
||||
write_pivot_table(document.root());
|
||||
break;
|
||||
case relationship::type::shared_string_table:
|
||||
write_shared_string_table(document.root());
|
||||
break;
|
||||
case relationship::type::shared_workbook_revision_headers:
|
||||
write_shared_workbook_revision_headers(document.root());
|
||||
break;
|
||||
case relationship::type::styles:
|
||||
write_styles(document.root());
|
||||
break;
|
||||
case relationship::type::theme:
|
||||
write_theme(document.root());
|
||||
break;
|
||||
case relationship::type::volatile_dependencies:
|
||||
write_volatile_dependencies(document.root());
|
||||
break;
|
||||
case relationship::type::worksheet:
|
||||
write_worksheet(document.root(), rel);
|
||||
break;
|
||||
write_document_to_archive(document, rel.get_target().get_path(), destination_);
|
||||
}
|
||||
|
||||
std::ostringstream document_stream;
|
||||
document.save(document_stream);
|
||||
destination_.write_string(document_stream.str(), rel.get_target_uri());
|
||||
}
|
||||
|
||||
// Unknown Parts
|
||||
|
@ -687,7 +640,7 @@ void xlsx_producer::write_manifest()
|
|||
auto types_node = content_types_document.append_child("Types");
|
||||
types_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/package/2006/content-types");
|
||||
|
||||
for (const auto &extension : source_.get_manifest().get_default_type_extensions())
|
||||
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());
|
||||
|
@ -695,32 +648,31 @@ void xlsx_producer::write_manifest()
|
|||
default_node.append_attribute("ContentType").set_value(content_type.c_str());
|
||||
}
|
||||
|
||||
for (const auto &part : source_.get_manifest().get_overriden_parts())
|
||||
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.to_string('/')).c_str());
|
||||
auto content_type = source_.get_manifest().get_content_type_string(part);
|
||||
override_node.append_attribute("PartName").set_value(part.string().c_str());
|
||||
auto content_type = source_.get_manifest().get_override_type(part);
|
||||
override_node.append_attribute("ContentType").set_value(content_type.c_str());
|
||||
}
|
||||
|
||||
for (const auto &part : source_.get_manifest().get_parts_with_relationships())
|
||||
for (const auto &part : source_.get_manifest().get_parts())
|
||||
{
|
||||
auto part_rels = source_.get_manifest().get_part_relationships(part);
|
||||
auto part_rels = source_.get_manifest().get_relationships(part);
|
||||
|
||||
if (part_rels.empty()) continue;
|
||||
|
||||
pugi::xml_document part_rels_document;
|
||||
write_relationships(part_rels, part_rels_document.root());
|
||||
path rels_path = part.parent().append("_rels").append(part.basename() + ".rels");
|
||||
path parent(part.parent().string().front() == '/' ? part.parent().string().substr(1) : part.parent().string());
|
||||
path rels_path(parent.append("_rels").append(part.filename() + ".rels").string());
|
||||
write_document_to_archive(part_rels_document, rels_path, destination_);
|
||||
}
|
||||
|
||||
write_document_to_archive(content_types_document, path("[Content_Types].xml"), destination_);
|
||||
|
||||
pugi::xml_document package_rels_document;
|
||||
write_relationships(source_.get_manifest().get_package_relationships(), package_rels_document);
|
||||
write_document_to_archive(package_rels_document, path("_rels/.rels"), destination_);
|
||||
}
|
||||
|
||||
void xlsx_producer::write_extended_properties(pugi::xml_node root)
|
||||
void xlsx_producer::write_extended_properties(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto properties_node = root.append_child("Properties");
|
||||
|
||||
|
@ -765,7 +717,7 @@ void xlsx_producer::write_extended_properties(pugi::xml_node root)
|
|||
}
|
||||
}
|
||||
|
||||
void xlsx_producer::write_core_properties(pugi::xml_node root)
|
||||
void xlsx_producer::write_core_properties(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto core_properties_node = root.append_child("cp:coreProperties");
|
||||
|
||||
|
@ -788,14 +740,14 @@ void xlsx_producer::write_core_properties(pugi::xml_node root)
|
|||
core_properties_node.append_child("cp:category");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_custom_properties(pugi::xml_node root)
|
||||
void xlsx_producer::write_custom_properties(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto properties_node = root.append_child("Properties");
|
||||
/*auto properties_node = */root.append_child("Properties");
|
||||
}
|
||||
|
||||
// Write SpreadsheetML-Specific Package Parts
|
||||
|
||||
void xlsx_producer::write_workbook(pugi::xml_node root)
|
||||
void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
std::size_t num_visible = 0;
|
||||
|
||||
|
@ -842,14 +794,13 @@ void xlsx_producer::write_workbook(pugi::xml_node root)
|
|||
|
||||
auto sheets_node = workbook_node.append_child("sheets");
|
||||
auto defined_names_node = workbook_node.append_child("definedNames");
|
||||
std::size_t index = 1;
|
||||
|
||||
auto wb_rel = source_.d_->manifest_.get_package_relationship(xlnt::relationship::type::office_document);
|
||||
auto wb_rel = source_.d_->manifest_.get_relationship(path("/"), xlnt::relationship::type::office_document);
|
||||
|
||||
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_part_relationship(wb_rel.get_target_uri(), sheet_rel_id);
|
||||
auto sheet_rel = source_.d_->manifest_.get_relationship(wb_rel.get_target().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());
|
||||
|
@ -893,51 +844,118 @@ void xlsx_producer::write_workbook(pugi::xml_node root)
|
|||
defined_name_node.text().set(target_string.c_str());
|
||||
}
|
||||
*/
|
||||
|
||||
for (const auto &child_rel : source_.get_manifest().get_relationships(rel.get_target().get_path()))
|
||||
{
|
||||
pugi::xml_document document;
|
||||
|
||||
switch (child_rel.get_type())
|
||||
{
|
||||
case relationship::type::calculation_chain:
|
||||
write_calculation_chain(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::chartsheet:
|
||||
write_chartsheet(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::connections:
|
||||
write_connections(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::custom_xml_mappings:
|
||||
write_custom_xml_mappings(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::dialogsheet:
|
||||
write_dialogsheet(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::external_workbook_references:
|
||||
write_external_workbook_references(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::metadata:
|
||||
write_metadata(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::pivot_table:
|
||||
write_pivot_table(child_rel, document.root());
|
||||
break;
|
||||
case relationship::type::shared_string_table:
|
||||
write_shared_string_table(child_rel, document.root());
|
||||
break;
|
||||
case relationship::type::shared_workbook_revision_headers:
|
||||
write_shared_workbook_revision_headers(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::styles:
|
||||
write_styles(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::theme:
|
||||
write_theme(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::volatile_dependencies:
|
||||
write_volatile_dependencies(child_rel, document.root());
|
||||
break;
|
||||
|
||||
case relationship::type::worksheet:
|
||||
write_worksheet(child_rel, document.root());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
write_document_to_archive(document, child_rel.get_target().get_path(), destination_);
|
||||
}
|
||||
}
|
||||
|
||||
// Write Workbook Relationship Target Parts
|
||||
|
||||
void xlsx_producer::write_calculation_chain(pugi::xml_node root)
|
||||
void xlsx_producer::write_calculation_chain(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto calc_chain_node = root.append_child("calcChain");
|
||||
/*auto calc_chain_node = */root.append_child("calcChain");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_chartsheet(pugi::xml_node root, const relationship &rel)
|
||||
void xlsx_producer::write_chartsheet(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto chartsheet_node = root.append_child("chartsheet");
|
||||
/*auto chartsheet_node = */root.append_child("chartsheet");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_connections(pugi::xml_node root)
|
||||
void xlsx_producer::write_connections(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto connections_node = root.append_child("connections");
|
||||
/*auto connections_node = */root.append_child("connections");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_custom_xml_mappings(pugi::xml_node root)
|
||||
void xlsx_producer::write_custom_xml_mappings(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto map_info_node = root.append_child("MapInfo");
|
||||
/*auto map_info_node = */root.append_child("MapInfo");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_dialogsheet(pugi::xml_node root, const relationship &rel)
|
||||
void xlsx_producer::write_dialogsheet(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto dialogsheet_node = root.append_child("dialogsheet");
|
||||
/*auto dialogsheet_node = */root.append_child("dialogsheet");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_external_workbook_references(pugi::xml_node root)
|
||||
void xlsx_producer::write_external_workbook_references(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto external_link_node = root.append_child("externalLink");
|
||||
/*auto external_link_node = */root.append_child("externalLink");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_metadata(pugi::xml_node root)
|
||||
void xlsx_producer::write_metadata(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto metadata_node = root.append_child("metadata");
|
||||
/*auto metadata_node = */root.append_child("metadata");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_pivot_table(pugi::xml_node root)
|
||||
void xlsx_producer::write_pivot_table(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto pivot_table_definition_node = root.append_child("pivotTableDefinition");
|
||||
/*auto pivot_table_definition_node = */root.append_child("pivotTableDefinition");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_shared_string_table(pugi::xml_node root)
|
||||
void xlsx_producer::write_shared_string_table(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto sst_node = root.append_child("sst");
|
||||
|
||||
|
@ -997,22 +1015,22 @@ void xlsx_producer::write_shared_string_table(pugi::xml_node root)
|
|||
}
|
||||
}
|
||||
|
||||
void xlsx_producer::write_shared_workbook_revision_headers(pugi::xml_node root)
|
||||
void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto headers_node = root.append_child("headers");
|
||||
/*auto headers_node = */root.append_child("headers");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_shared_workbook(pugi::xml_node root)
|
||||
void xlsx_producer::write_shared_workbook(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto revisions_node = root.append_child("revisions");
|
||||
/*auto revisions_node = */root.append_child("revisions");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_shared_workbook_user_data(pugi::xml_node root)
|
||||
void xlsx_producer::write_shared_workbook_user_data(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto users_node = root.append_child("users");
|
||||
/*auto users_node = */root.append_child("users");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_styles(pugi::xml_node root)
|
||||
void xlsx_producer::write_styles(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto stylesheet_node = root.append_child("styleSheet");
|
||||
stylesheet_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
|
@ -1067,7 +1085,7 @@ void xlsx_producer::write_styles(pugi::xml_node root)
|
|||
}
|
||||
}
|
||||
|
||||
void xlsx_producer::write_theme(pugi::xml_node root)
|
||||
void xlsx_producer::write_theme(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto theme_node = root.append_child("a:theme");
|
||||
theme_node.append_attribute("xmlns:a").set_value(constants::get_namespace("drawingml").c_str());
|
||||
|
@ -1403,12 +1421,12 @@ void xlsx_producer::write_theme(pugi::xml_node root)
|
|||
theme_node.append_child("a:extraClrSchemeLst");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_volatile_dependencies(pugi::xml_node root)
|
||||
void xlsx_producer::write_volatile_dependencies(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto vol_types_node = root.append_child("volTypes");
|
||||
/*auto vol_types_node = */root.append_child("volTypes");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_worksheet(pugi::xml_node root, const relationship &rel)
|
||||
void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto worksheet_node = root.append_child("worksheet");
|
||||
worksheet_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
|
@ -1702,9 +1720,9 @@ void xlsx_producer::write_worksheet(pugi::xml_node root, const relationship &rel
|
|||
}
|
||||
}
|
||||
|
||||
if (!source_.impl().manifest_.get_part_relationships(rel.get_target_uri()).empty())
|
||||
if (!source_.impl().manifest_.get_relationships(rel.get_target().get_path()).empty())
|
||||
{
|
||||
auto sheet_rels = source_.impl().manifest_.get_part_relationships(rel.get_target_uri());
|
||||
auto sheet_rels = source_.impl().manifest_.get_relationships(rel.get_target().get_path());
|
||||
std::vector<relationship> hyperlink_sheet_rels;
|
||||
|
||||
for (const auto &sheet_rel : sheet_rels)
|
||||
|
@ -1722,7 +1740,7 @@ void xlsx_producer::write_worksheet(pugi::xml_node root, const relationship &rel
|
|||
for (const auto &hyperlink_rel : hyperlink_sheet_rels)
|
||||
{
|
||||
auto hyperlink_node = hyperlinks_node.append_child("hyperlink");
|
||||
hyperlink_node.append_attribute("display").set_value(hyperlink_rel.get_target_uri().to_string('/').c_str());
|
||||
hyperlink_node.append_attribute("display").set_value(hyperlink_rel.get_target().get_path().string().c_str());
|
||||
hyperlink_node.append_attribute("ref").set_value(hyperlink_references.at(hyperlink_rel.get_id()).c_str());
|
||||
hyperlink_node.append_attribute("r:id").set_value(hyperlink_rel.get_id().c_str());
|
||||
}
|
||||
|
@ -1801,14 +1819,14 @@ void xlsx_producer::write_worksheet(pugi::xml_node root, const relationship &rel
|
|||
|
||||
// Sheet Relationship Target Parts
|
||||
|
||||
void xlsx_producer::write_comments(pugi::xml_node root)
|
||||
void xlsx_producer::write_comments(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto comments_node = root.append_child("comments");
|
||||
/*auto comments_node = */root.append_child("comments");
|
||||
}
|
||||
|
||||
void xlsx_producer::write_drawings(pugi::xml_node root)
|
||||
void xlsx_producer::write_drawings(const relationship &rel, pugi::xml_node root)
|
||||
{
|
||||
auto ws_dr_node = root.append_child("wsDr");
|
||||
/*auto ws_dr_node = */root.append_child("wsDr");
|
||||
}
|
||||
|
||||
// Other Parts
|
||||
|
@ -1825,5 +1843,12 @@ void xlsx_producer::write_unknown_relationships()
|
|||
{
|
||||
}
|
||||
|
||||
void xlsx_producer::write_thumbnail(const relationship &rel)
|
||||
{
|
||||
const auto &thumbnail = source_.get_thumbnail();
|
||||
std::string thumbnail_string(thumbnail.begin(), thumbnail.end());
|
||||
destination_.write_string(thumbnail_string, rel.get_target().get_path());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namepsace xlnt
|
||||
|
|
|
@ -63,38 +63,39 @@ private:
|
|||
// Package Parts
|
||||
|
||||
void write_manifest();
|
||||
void write_core_properties(pugi::xml_node root);
|
||||
void write_extended_properties(pugi::xml_node root);
|
||||
void write_custom_properties(pugi::xml_node root);
|
||||
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_thumbnail(const relationship &rel);
|
||||
|
||||
// SpreadsheetML-Specific Package Parts
|
||||
|
||||
void write_workbook(pugi::xml_node root);
|
||||
void write_workbook(const relationship &rel, pugi::xml_node root);
|
||||
|
||||
// Workbook Relationship Target Parts
|
||||
|
||||
void write_calculation_chain(pugi::xml_node root);
|
||||
void write_connections(pugi::xml_node root);
|
||||
void write_custom_xml_mappings(pugi::xml_node root);
|
||||
void write_external_workbook_references(pugi::xml_node root);
|
||||
void write_metadata(pugi::xml_node root);
|
||||
void write_pivot_table(pugi::xml_node root);
|
||||
void write_shared_string_table(pugi::xml_node root);
|
||||
void write_shared_workbook_revision_headers(pugi::xml_node root);
|
||||
void write_shared_workbook(pugi::xml_node root);
|
||||
void write_shared_workbook_user_data(pugi::xml_node root);
|
||||
void write_styles(pugi::xml_node root);
|
||||
void write_theme(pugi::xml_node root);
|
||||
void write_volatile_dependencies(pugi::xml_node root);
|
||||
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_chartsheet(pugi::xml_node root, const relationship &rel);
|
||||
void write_dialogsheet(pugi::xml_node root, const relationship &rel);
|
||||
void write_worksheet(pugi::xml_node root, const relationship &rel);
|
||||
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);
|
||||
|
||||
// Sheet Relationship Target Parts
|
||||
|
||||
void write_comments(pugi::xml_node root);
|
||||
void write_drawings(pugi::xml_node root);
|
||||
void write_comments(const relationship &rel, pugi::xml_node root);
|
||||
void write_drawings(const relationship &rel, pugi::xml_node root);
|
||||
|
||||
// Other Parts
|
||||
|
||||
|
|
|
@ -21,310 +21,169 @@
|
|||
//
|
||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
#include <xlnt/utils/exceptions.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string to_string(xlnt::content_type type)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
xlnt::content_type from_string(const std::string &type_string)
|
||||
{
|
||||
return xlnt::content_type::unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
void manifest::clear()
|
||||
{
|
||||
clear_types();
|
||||
clear_relationships();
|
||||
part_infos_.clear();
|
||||
default_content_types_.clear();
|
||||
override_content_types_.clear();
|
||||
relationships_.clear();
|
||||
}
|
||||
|
||||
void manifest::clear_types()
|
||||
bool manifest::has_relationship(const path &part, relationship::type type) const
|
||||
{
|
||||
clear_default_types();
|
||||
clear_override_types();
|
||||
}
|
||||
if (relationships_.find(part) == relationships_.end()) return false;
|
||||
|
||||
void manifest::clear_default_types()
|
||||
for (const auto &rel : relationships_.at(part))
|
||||
{
|
||||
extension_content_type_map_.clear();
|
||||
}
|
||||
|
||||
void manifest::clear_override_types()
|
||||
{
|
||||
for (auto &info : part_infos_)
|
||||
{
|
||||
info.second.content_type.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void manifest::clear_relationships()
|
||||
{
|
||||
clear_package_relationships();
|
||||
clear_part_relationships();
|
||||
}
|
||||
|
||||
void manifest::clear_package_relationships()
|
||||
{
|
||||
package_relationships_.clear();
|
||||
}
|
||||
|
||||
void manifest::clear_part_relationships()
|
||||
{
|
||||
for (auto &info : part_infos_)
|
||||
{
|
||||
info.second.relationships.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool manifest::has_package_relationship(relationship::type type) const
|
||||
{
|
||||
for (const auto &rel : package_relationships_)
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (rel.second.get_type() == type) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool manifest::has_part_relationship(const path &part, relationship::type type) const
|
||||
relationship manifest::get_relationship(const path &part, relationship::type type) const
|
||||
{
|
||||
for (const auto &rel : part_infos_.at(part).relationships)
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (relationships_.find(part) == relationships_.end()) throw key_not_found();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
relationship manifest::get_package_relationship(relationship::type type) const
|
||||
for (const auto &rel : relationships_.at(part))
|
||||
{
|
||||
for (const auto &rel : package_relationships_)
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
{
|
||||
return rel;
|
||||
}
|
||||
if (rel.second.get_type() == type) return rel.second;
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
std::vector<relationship> manifest::get_package_relationships(relationship::type type) const
|
||||
std::vector<relationship> manifest::get_relationships(const path &part, relationship::type type) const
|
||||
{
|
||||
std::vector<relationship> matches;
|
||||
|
||||
for (const auto &rel : package_relationships_)
|
||||
for (const auto &rel : relationships_.at(part))
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
if (rel.second.get_type() == type)
|
||||
{
|
||||
matches.push_back(rel);
|
||||
matches.push_back(rel.second);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
relationship manifest::get_part_relationship(const path &part, relationship::type type) const
|
||||
std::string manifest::get_content_type(const path &part) const
|
||||
{
|
||||
for (const auto &rel : part_infos_.at(part).relationships)
|
||||
if (has_override_type(part))
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
{
|
||||
return rel;
|
||||
return get_override_type(part);
|
||||
}
|
||||
|
||||
if (has_default_type(part.extension()))
|
||||
{
|
||||
return get_default_type(part.extension());
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
std::vector<relationship> manifest::get_part_relationships(const path &part, relationship::type type) const
|
||||
{
|
||||
std::vector<relationship> matches;
|
||||
|
||||
for (const auto &rel : part_infos_.at(part).relationships)
|
||||
{
|
||||
if (rel.get_type() == type)
|
||||
{
|
||||
matches.push_back(rel);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
content_type manifest::get_content_type(const path &part) const
|
||||
{
|
||||
return from_string(get_content_type_string(part));
|
||||
}
|
||||
|
||||
std::string manifest::get_content_type_string(const path &part) const
|
||||
{
|
||||
if (part_infos_.find(part) == part_infos_.end())
|
||||
{
|
||||
auto extension = part.extension();
|
||||
|
||||
if (has_default_type(extension))
|
||||
{
|
||||
return get_default_type(extension);
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
return part_infos_.at(part).content_type;
|
||||
}
|
||||
|
||||
void manifest::register_override_type(const path &part, const std::string &content_type)
|
||||
{
|
||||
part_infos_[part] = { content_type, {} };
|
||||
override_content_types_[part] = content_type;
|
||||
}
|
||||
|
||||
std::string manifest::register_package_relationship(relationship::type type, const path &target_uri, target_mode mode)
|
||||
{
|
||||
return register_package_relationship(type, target_uri, mode, next_package_relationship_id());
|
||||
}
|
||||
|
||||
std::string manifest::register_package_relationship(relationship::type type, const path &target_uri, target_mode mode, const std::string &rel_id)
|
||||
{
|
||||
if (has_package_relationship(rel_id))
|
||||
{
|
||||
throw invalid_parameter();
|
||||
}
|
||||
|
||||
relationship rel(rel_id, type, target_uri, mode);
|
||||
package_relationships_.push_back(rel);
|
||||
|
||||
return rel_id;
|
||||
}
|
||||
|
||||
bool manifest::has_package_relationship(const std::string &rel_id) const
|
||||
{
|
||||
for (const auto &rel : package_relationships_)
|
||||
{
|
||||
if (rel.get_id() == rel_id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<path> manifest::get_overriden_parts() const
|
||||
std::vector<path> manifest::get_parts_with_overriden_types() const
|
||||
{
|
||||
std::vector<path> overriden;
|
||||
|
||||
for (const auto &part : part_infos_)
|
||||
{
|
||||
if (!part.second.content_type.empty())
|
||||
for (const auto &part : override_content_types_)
|
||||
{
|
||||
overriden.push_back(part.first);
|
||||
}
|
||||
}
|
||||
|
||||
return overriden;
|
||||
}
|
||||
|
||||
std::vector<relationship> manifest::get_package_relationships() const
|
||||
std::vector<relationship> manifest::get_relationships(const path &part) const
|
||||
{
|
||||
return package_relationships_;
|
||||
if (relationships_.find(part) == relationships_.end())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
relationship manifest::get_package_relationship(const std::string &rel_id) const
|
||||
std::vector<relationship> relationships;
|
||||
|
||||
for (const auto &rel : relationships_.at(part))
|
||||
{
|
||||
for (const auto rel : package_relationships_)
|
||||
relationships.push_back(rel.second);
|
||||
}
|
||||
|
||||
return relationships;
|
||||
}
|
||||
|
||||
relationship manifest::get_relationship(const path &part, const std::string &rel_id) const
|
||||
{
|
||||
if (rel.get_id() == rel_id)
|
||||
if (relationships_.find(part) == relationships_.end())
|
||||
{
|
||||
return rel;
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
for (const auto &rel : relationships_.at(part))
|
||||
{
|
||||
if (rel.second.get_id() == rel_id)
|
||||
{
|
||||
return rel.second;
|
||||
}
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
std::vector<relationship> manifest::get_part_relationships(const path &part) const
|
||||
std::vector<path> manifest::get_parts() const
|
||||
{
|
||||
if (part_infos_.find(part) == part_infos_.end())
|
||||
{
|
||||
throw key_not_found();
|
||||
}
|
||||
std::unordered_set<path> parts;
|
||||
|
||||
return part_infos_.at(part).relationships;
|
||||
}
|
||||
for (const auto &part_rels : relationships_)
|
||||
{
|
||||
parts.insert(part_rels.first);
|
||||
|
||||
relationship manifest::get_part_relationship(const path &part, const std::string &rel_id) const
|
||||
for (const auto &rel : part_rels.second)
|
||||
{
|
||||
if (part_infos_.find(part) == part_infos_.end())
|
||||
if (rel.second.get_target_mode() == target_mode::internal)
|
||||
{
|
||||
throw key_not_found();
|
||||
parts.insert(rel.second.get_target().get_path());
|
||||
}
|
||||
|
||||
for (const auto &rel : part_infos_.at(part).relationships)
|
||||
{
|
||||
if (rel.get_id() == rel_id)
|
||||
{
|
||||
return rel;
|
||||
}
|
||||
}
|
||||
|
||||
throw key_not_found();
|
||||
return std::vector<path>(parts.begin(), parts.end());
|
||||
}
|
||||
|
||||
std::vector<path> manifest::get_parts_with_relationships() const
|
||||
std::string manifest::register_relationship(const uri &source, relationship::type type, const uri &target, target_mode mode)
|
||||
{
|
||||
std::vector<path> with_relationships;
|
||||
|
||||
for (const auto &info : part_infos_)
|
||||
{
|
||||
if (!info.second.relationships.empty())
|
||||
{
|
||||
with_relationships.push_back(info.first);
|
||||
}
|
||||
return register_relationship(source, type, target, mode, next_relationship_id(source.get_path()));
|
||||
}
|
||||
|
||||
return with_relationships;
|
||||
}
|
||||
|
||||
std::string manifest::register_part_relationship(const path &source_uri, relationship::type type, const path &target_uri, target_mode mode)
|
||||
std::string manifest::register_relationship(const uri &source, relationship::type type, const uri &target, target_mode mode, const std::string &rel_id)
|
||||
{
|
||||
return register_part_relationship(source_uri, type, target_uri, mode, next_relationship_id(source_uri));
|
||||
}
|
||||
|
||||
std::string manifest::register_part_relationship(const path &source_uri, relationship::type type, const path &target_uri, target_mode mode, const std::string &rel_id)
|
||||
{
|
||||
relationship rel(rel_id, type, path(target_uri), mode);
|
||||
part_infos_.at(source_uri).relationships.push_back(rel);
|
||||
relationships_[source.get_path()][rel_id] = relationship(rel_id, type, source, target, mode);
|
||||
return rel_id;
|
||||
}
|
||||
|
||||
bool manifest::has_default_type(const std::string &extension) const
|
||||
{
|
||||
return extension_content_type_map_.find(extension) != extension_content_type_map_.end();
|
||||
return default_content_types_.find(extension) != default_content_types_.end();
|
||||
}
|
||||
|
||||
std::vector<std::string> manifest::get_default_type_extensions() const
|
||||
std::vector<std::string> manifest::get_extensions_with_default_types() const
|
||||
{
|
||||
std::vector<std::string> extensions;
|
||||
|
||||
for (const auto &extension_type_pair : extension_content_type_map_)
|
||||
for (const auto &extension_type_pair : default_content_types_)
|
||||
{
|
||||
extensions.push_back(extension_type_pair.first);
|
||||
}
|
||||
|
@ -334,54 +193,52 @@ std::vector<std::string> manifest::get_default_type_extensions() const
|
|||
|
||||
std::string manifest::get_default_type(const std::string &extension) const
|
||||
{
|
||||
if (extension_content_type_map_.find(extension) == extension_content_type_map_.end())
|
||||
if (default_content_types_.find(extension) == default_content_types_.end())
|
||||
{
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
return extension_content_type_map_.at(extension);
|
||||
return default_content_types_.at(extension);
|
||||
}
|
||||
|
||||
void manifest::register_default_type(const std::string &extension, const std::string &content_type)
|
||||
{
|
||||
extension_content_type_map_[extension] = content_type;
|
||||
default_content_types_[extension] = content_type;
|
||||
}
|
||||
|
||||
void manifest::unregister_default_type(const std::string &extension)
|
||||
{
|
||||
extension_content_type_map_.erase(extension);
|
||||
}
|
||||
|
||||
std::string manifest::next_package_relationship_id() const
|
||||
{
|
||||
std::string r_id("rId");
|
||||
std::size_t index = 1;
|
||||
|
||||
while (std::find_if(package_relationships_.begin(), package_relationships_.end(),
|
||||
[&](const relationship &r) { return r.get_id() == r_id + std::to_string(index); })
|
||||
!= package_relationships_.end())
|
||||
{
|
||||
++index;
|
||||
}
|
||||
|
||||
return r_id + std::to_string(index);
|
||||
default_content_types_.erase(extension);
|
||||
}
|
||||
|
||||
std::string manifest::next_relationship_id(const path &part) const
|
||||
{
|
||||
std::string r_id("rId");
|
||||
if (relationships_.find(part) == relationships_.end()) return "rId1";
|
||||
|
||||
std::size_t index = 1;
|
||||
const auto &part_rels = relationships_.at(part);
|
||||
|
||||
const auto &part_rels = get_part_relationships(part);
|
||||
|
||||
while (std::find_if(part_rels.begin(), part_rels.end(),
|
||||
[&](const relationship &r) { return r.get_id() == r_id + std::to_string(index); })
|
||||
!= part_rels.end())
|
||||
while (part_rels.find("rId" + std::to_string(index)) != part_rels.end())
|
||||
{
|
||||
++index;
|
||||
}
|
||||
|
||||
return r_id + std::to_string(index);
|
||||
return "rId" + std::to_string(index);
|
||||
}
|
||||
|
||||
bool manifest::has_override_type(const xlnt::path &part) const
|
||||
{
|
||||
return override_content_types_.find(part) != override_content_types_.end();
|
||||
}
|
||||
|
||||
std::string manifest::get_override_type(const xlnt::path &part) const
|
||||
{
|
||||
if (!has_override_type(part))
|
||||
{
|
||||
throw key_not_found();
|
||||
}
|
||||
|
||||
return override_content_types_.at(part);
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -30,7 +30,7 @@ relationship::relationship()
|
|||
{
|
||||
}
|
||||
|
||||
relationship::relationship(const std::string &id, type t, const path &source, const path &target, target_mode mode)
|
||||
relationship::relationship(const std::string &id, type t, const uri &source, const uri &target, target_mode mode)
|
||||
: id_(id),
|
||||
type_(t),
|
||||
source_(source),
|
||||
|
@ -44,17 +44,17 @@ std::string relationship::get_id() const
|
|||
return id_;
|
||||
}
|
||||
|
||||
target_mode relationship::get_mode() const
|
||||
target_mode relationship::get_target_mode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
path relationship::get_source() const
|
||||
uri relationship::get_source() const
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
|
||||
path relationship::get_target() const
|
||||
uri relationship::get_target() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ bool relationship::operator==(const relationship &rhs) const
|
|||
{
|
||||
return type_ == rhs.type_
|
||||
&& id_ == rhs.id_
|
||||
&& source_ == the.source_
|
||||
&& source_ == rhs.source_
|
||||
&& target_ == rhs.target_
|
||||
&& mode_ == rhs.mode_;
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ public:
|
|||
|
||||
bool files_equal(const xlnt::path &left, const xlnt::path &right)
|
||||
{
|
||||
if(left.to_string() == right.to_string())
|
||||
if(left.string() == right.string())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ifstream stream_left(left.to_string(), std::ios::binary);
|
||||
std::ifstream stream_right(right.to_string(), std::ios::binary);
|
||||
std::ifstream stream_left(left.string(), std::ios::binary);
|
||||
std::ifstream stream_right(right.string(), std::ios::binary);
|
||||
|
||||
while(stream_left && stream_right)
|
||||
{
|
||||
|
@ -48,9 +48,9 @@ public:
|
|||
{
|
||||
temporary_file temp;
|
||||
|
||||
std::ifstream in_stream(existing_file.to_string(), std::ios::binary);
|
||||
std::ifstream in_stream(existing_file.string(), std::ios::binary);
|
||||
xlnt::zip_file f(in_stream);
|
||||
std::ofstream out_stream(temp.get_path().to_string(), std::ios::binary);
|
||||
std::ofstream out_stream(temp.get_path().string(), std::ios::binary);
|
||||
f.save(out_stream);
|
||||
out_stream.close();
|
||||
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
temporary_file temp_file;
|
||||
|
||||
std::vector<std::uint8_t> source_bytes;
|
||||
std::ifstream in_stream(existing_file.to_string(), std::ios::binary);
|
||||
std::ifstream in_stream(existing_file.string(), std::ios::binary);
|
||||
|
||||
while(in_stream)
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ public:
|
|||
{
|
||||
xlnt::zip_file f(existing_file);
|
||||
auto info = f.getinfo(xlnt::path("text.txt"));
|
||||
TS_ASSERT(info.filename.to_string() == "text.txt");
|
||||
TS_ASSERT(info.filename.string() == "text.txt");
|
||||
}
|
||||
|
||||
void test_infolist()
|
||||
|
|
28
source/packaging/uri.cpp
Normal file
28
source/packaging/uri.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <xlnt/packaging/uri.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
uri::uri()
|
||||
{
|
||||
}
|
||||
|
||||
uri::uri(const std::string &uri_string) : path_(uri_string)
|
||||
{
|
||||
}
|
||||
|
||||
std::string uri::to_string() const
|
||||
{
|
||||
return path_.string();
|
||||
}
|
||||
|
||||
path uri::get_path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
bool operator==(const uri &left, const uri &right)
|
||||
{
|
||||
return left.to_string() == right.to_string();
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -185,11 +185,11 @@ void zip_file::load(std::istream &stream)
|
|||
void zip_file::load(const path &filename)
|
||||
{
|
||||
filename_ = filename;
|
||||
std::ifstream stream(filename.to_string(), std::ios::binary);
|
||||
std::ifstream stream(filename.string(), std::ios::binary);
|
||||
|
||||
if (!stream.good())
|
||||
{
|
||||
throw invalid_file(filename.to_string());
|
||||
throw invalid_file(filename.string());
|
||||
}
|
||||
|
||||
reset();
|
||||
|
@ -197,7 +197,7 @@ void zip_file::load(const path &filename)
|
|||
|
||||
if (buffer_.empty())
|
||||
{
|
||||
throw invalid_file(filename.to_string() + " - empty file");
|
||||
throw invalid_file(filename.string() + " - empty file");
|
||||
}
|
||||
|
||||
remove_comment();
|
||||
|
@ -220,7 +220,7 @@ void zip_file::load(const std::vector<unsigned char> &bytes)
|
|||
void zip_file::save(const path &filename)
|
||||
{
|
||||
filename_ = filename;
|
||||
std::ofstream stream(filename.to_string(), std::ios::binary);
|
||||
std::ofstream stream(filename.string(), std::ios::binary);
|
||||
save(stream);
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ zip_info zip_file::getinfo(const path &name)
|
|||
start_read();
|
||||
}
|
||||
|
||||
int index = mz_zip_reader_locate_file(archive_.get(), name.to_string('/').c_str(), nullptr, 0);
|
||||
int index = mz_zip_reader_locate_file(archive_.get(), name.string().c_str(), nullptr, 0);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
|
@ -462,18 +462,14 @@ void zip_file::write_file(const path &filename)
|
|||
|
||||
if (filename.is_absolute())
|
||||
{
|
||||
auto split = filename.split();
|
||||
|
||||
auto iter = split.begin() + 1;
|
||||
arcname = path();
|
||||
bool first = true;
|
||||
|
||||
for (auto part : filename)
|
||||
while (iter != split.end())
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
arcname.append(part);
|
||||
arcname.append(*iter++);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +478,7 @@ void zip_file::write_file(const path &filename)
|
|||
|
||||
void zip_file::write_file(const path &filename, const path &arcname)
|
||||
{
|
||||
std::fstream file(filename.to_string(), std::ios::binary | std::ios::in);
|
||||
std::fstream file(filename.string(), std::ios::binary | std::ios::in);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
|
@ -497,13 +493,13 @@ void zip_file::write_string(const std::string &bytes, const path &arcname)
|
|||
start_write();
|
||||
}
|
||||
|
||||
mz_zip_writer_add_mem(archive_.get(), arcname.to_string('/').c_str(),
|
||||
mz_zip_writer_add_mem(archive_.get(), arcname.string().c_str(),
|
||||
bytes.data(), bytes.size(), MZ_BEST_COMPRESSION);
|
||||
}
|
||||
|
||||
void zip_file::write_string(const std::string &bytes, const zip_info &info)
|
||||
{
|
||||
if (info.filename.to_string().empty() || info.date_time.year < 1980)
|
||||
if (info.filename.string().empty() || info.date_time.year < 1980)
|
||||
{
|
||||
throw std::runtime_error("must specify a filename and valid date (year >= 1980");
|
||||
}
|
||||
|
@ -515,7 +511,7 @@ void zip_file::write_string(const std::string &bytes, const zip_info &info)
|
|||
|
||||
auto crc = crc32buf(bytes.c_str(), bytes.size());
|
||||
|
||||
mz_zip_writer_add_mem_ex(archive_.get(), info.filename.to_string('/').c_str(), bytes.data(), bytes.size(),
|
||||
mz_zip_writer_add_mem_ex(archive_.get(), info.filename.string().c_str(), bytes.data(), bytes.size(),
|
||||
info.comment.c_str(), static_cast<mz_uint16>(info.comment.size()),
|
||||
MZ_BEST_COMPRESSION, 0, crc);
|
||||
}
|
||||
|
@ -524,7 +520,7 @@ std::string zip_file::read(const zip_info &info)
|
|||
{
|
||||
std::size_t size;
|
||||
void *data_raw = mz_zip_reader_extract_file_to_heap(archive_.get(),
|
||||
info.filename.to_string('/').c_str(), &size, 0);
|
||||
info.filename.string().c_str(), &size, 0);
|
||||
|
||||
if (data_raw == nullptr)
|
||||
{
|
||||
|
@ -550,7 +546,7 @@ bool zip_file::has_file(const path &name)
|
|||
start_read();
|
||||
}
|
||||
|
||||
int index = mz_zip_reader_locate_file(archive_.get(), name.to_string('/').c_str(), nullptr, 0);
|
||||
int index = mz_zip_reader_locate_file(archive_.get(), name.string().c_str(), nullptr, 0);
|
||||
|
||||
return index != -1;
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ std::array<std::uint8_t, 4> rgb_color::decode_hex_string(const std::string &hex_
|
|||
auto g = static_cast<std::uint8_t>((x >> 8) & 0xff);
|
||||
auto b = static_cast<std::uint8_t>(x & 0xff);
|
||||
|
||||
return { r, g, b, a };
|
||||
return { {r, g, b, a} };
|
||||
}
|
||||
|
||||
rgb_color::rgb_color(const std::string &hex_string)
|
||||
|
@ -181,7 +181,7 @@ rgb_color::rgb_color(const std::string &hex_string)
|
|||
}
|
||||
|
||||
rgb_color::rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a)
|
||||
: rgba_({r, g, b, a})
|
||||
: rgba_({{r, g, b, a}})
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -46,16 +46,8 @@ char system_separator()
|
|||
|
||||
bool is_root(const std::string &part)
|
||||
{
|
||||
return part.size() == 2 && part.back() == ':'
|
||||
&& part.front() >= 'A' && part.front() <= 'Z';
|
||||
}
|
||||
|
||||
std::string get_working_directory()
|
||||
{
|
||||
TCHAR buffer[MAX_PATH];
|
||||
GetCurrentDirectory(MAX_PATH, buffer);
|
||||
std::basic_string<TCHAR> working_directory(buffer);
|
||||
return std::string(working_directory.begin(), working_directory.end());
|
||||
return part == "/" || (part.size() == 2 && part.back() == ':'
|
||||
&& part.front() >= 'A' && part.front() <= 'Z');
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -67,21 +59,7 @@ char system_separator()
|
|||
|
||||
bool is_root(const std::string &part)
|
||||
{
|
||||
return part.empty();
|
||||
}
|
||||
|
||||
std::string get_working_directory()
|
||||
{
|
||||
std::size_t buffer_size = 100;
|
||||
std::vector<char> buffer(buffer_size, '\0');
|
||||
|
||||
while (getcwd(&buffer[0], buffer_size) == nullptr)
|
||||
{
|
||||
buffer_size *= 2;
|
||||
buffer.resize(buffer_size, '\0');
|
||||
}
|
||||
|
||||
return std::string(&buffer[0]);
|
||||
return part == "/";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -110,23 +88,6 @@ std::vector<std::string> split_path(const std::string &path, char delim)
|
|||
return split;
|
||||
}
|
||||
|
||||
std::vector<std::string> split_path_universal(const std::string &path)
|
||||
{
|
||||
auto initial = split_path(path, system_separator());
|
||||
|
||||
if (initial.size() == 1 && system_separator() == '\\')
|
||||
{
|
||||
auto alternative = split_path(path, '/');
|
||||
|
||||
if (alternative.size() > 1)
|
||||
{
|
||||
return alternative;
|
||||
}
|
||||
}
|
||||
|
||||
return initial;
|
||||
}
|
||||
|
||||
bool file_exists(const std::string &path)
|
||||
{
|
||||
struct stat info;
|
||||
|
@ -143,9 +104,9 @@ bool directory_exists(const std::string path)
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
char path::separator()
|
||||
char path::system_separator()
|
||||
{
|
||||
return system_separator();
|
||||
return ::system_separator();
|
||||
}
|
||||
|
||||
path::path()
|
||||
|
@ -153,11 +114,7 @@ path::path()
|
|||
|
||||
}
|
||||
|
||||
path::path(const std::string &path_string) : parts_(split_path_universal(path_string))
|
||||
{
|
||||
}
|
||||
|
||||
path::path(const std::string &path_string, char sep) : parts_(split_path(path_string, sep))
|
||||
path::path(const std::string &path_string) : internal_(path_string)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -170,88 +127,76 @@ bool path::is_relative() const
|
|||
|
||||
bool path::is_absolute() const
|
||||
{
|
||||
return !parts_.empty() && ::is_root(parts_.front());
|
||||
auto split_path = split();
|
||||
return !split_path.empty() && ::is_root(split_path.front());
|
||||
}
|
||||
|
||||
bool path::is_root() const
|
||||
{
|
||||
return parts_.size() == 1 && ::is_root(parts_.front());
|
||||
return ::is_root(internal_);
|
||||
}
|
||||
|
||||
path path::parent() const
|
||||
{
|
||||
path result;
|
||||
result.parts_ = parts_;
|
||||
if (is_root()) return *this;
|
||||
|
||||
if (result.parts_.size() > 1)
|
||||
{
|
||||
result.parts_.pop_back();
|
||||
}
|
||||
else
|
||||
auto split_path = split();
|
||||
|
||||
split_path.pop_back();
|
||||
|
||||
if (split_path.empty())
|
||||
{
|
||||
return path("");
|
||||
}
|
||||
|
||||
path result;
|
||||
|
||||
for (const auto &component : split_path)
|
||||
{
|
||||
result = result.append(component);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string path::basename() const
|
||||
std::string path::filename() const
|
||||
{
|
||||
return parts_.empty() ? "" : parts_.back();
|
||||
auto split_path = split();
|
||||
return split_path.empty() ? "" : split_path.back();
|
||||
}
|
||||
|
||||
std::string path::extension() const
|
||||
{
|
||||
auto base = basename();
|
||||
auto base = filename();
|
||||
auto last_dot = base.find_last_of('.');
|
||||
|
||||
if (last_dot == std::string::npos) return "";
|
||||
|
||||
return base.substr(last_dot + 1);
|
||||
return last_dot == std::string::npos ? "" : base.substr(last_dot + 1);
|
||||
}
|
||||
|
||||
// conversion
|
||||
|
||||
std::string path::to_string(char sep) const
|
||||
std::string path::string() const
|
||||
{
|
||||
if (parts_.empty()) return "";
|
||||
|
||||
std::string result;
|
||||
|
||||
for (const auto &part : parts_)
|
||||
{
|
||||
result.append(part);
|
||||
result.push_back(sep);
|
||||
return internal_;
|
||||
}
|
||||
|
||||
result.pop_back();
|
||||
|
||||
return result;
|
||||
std::vector<std::string> path::split() const
|
||||
{
|
||||
return split_path(internal_, guess_separator());
|
||||
}
|
||||
|
||||
path path::make_absolute(const path &base_path) const
|
||||
path path::resolve(const path &base_path) const
|
||||
{
|
||||
if (is_absolute())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
path copy = base_path;
|
||||
path copy(base_path.internal_);
|
||||
|
||||
for (const auto &part : parts_)
|
||||
for (const auto &part : split())
|
||||
{
|
||||
if (part == ".")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (part == ".." && copy.parts_.size() > 1)
|
||||
{
|
||||
copy.parts_.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
copy.parts_.push_back(part);
|
||||
}
|
||||
copy = copy.append(part);
|
||||
}
|
||||
|
||||
return copy;
|
||||
|
@ -266,120 +211,56 @@ bool path::exists() const
|
|||
|
||||
bool path::is_directory() const
|
||||
{
|
||||
return directory_exists(to_string());
|
||||
return directory_exists(string());
|
||||
}
|
||||
|
||||
bool path::is_file() const
|
||||
{
|
||||
return file_exists(to_string());
|
||||
return file_exists(string());
|
||||
}
|
||||
|
||||
// filesystem
|
||||
|
||||
std::string path::read_contents() const
|
||||
{
|
||||
std::ifstream f(to_string());
|
||||
std::ifstream f(string());
|
||||
std::ostringstream ss;
|
||||
ss << f.rdbuf();
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// mutators
|
||||
|
||||
path &path::append(const std::string &to_append)
|
||||
{
|
||||
parts_.push_back(to_append);
|
||||
return *this;
|
||||
}
|
||||
// append
|
||||
|
||||
path path::append(const std::string &to_append) const
|
||||
{
|
||||
path copy(*this);
|
||||
copy.append(to_append);
|
||||
path copy(internal_);
|
||||
|
||||
return copy;
|
||||
if (!internal_.empty() && internal_.back() != guess_separator())
|
||||
{
|
||||
copy.internal_.push_back(guess_separator());
|
||||
}
|
||||
|
||||
path &path::append(const path &to_append)
|
||||
{
|
||||
parts_.insert(parts_.end(), to_append.begin(), to_append.end());
|
||||
return *this;
|
||||
copy.internal_.append(to_append);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
path path::append(const path &to_append) const
|
||||
{
|
||||
path copy(*this);
|
||||
copy.append(to_append);
|
||||
|
||||
return copy;
|
||||
return append(to_append.string());
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
||||
path::iterator path::begin()
|
||||
char path::guess_separator() const
|
||||
{
|
||||
return parts_.begin();
|
||||
if (system_separator() == '/') return '/';
|
||||
if (is_absolute()) return internal_.at(2);
|
||||
return internal_.find('/') == std::string::npos ? '/' : '\\';
|
||||
}
|
||||
|
||||
path::iterator path::end()
|
||||
bool operator==(const path &left, const path &right)
|
||||
{
|
||||
return parts_.end();
|
||||
}
|
||||
|
||||
path::const_iterator path::begin() const
|
||||
{
|
||||
return cbegin();
|
||||
}
|
||||
|
||||
path::const_iterator path::end() const
|
||||
{
|
||||
return cend();
|
||||
}
|
||||
|
||||
path::const_iterator path::cbegin() const
|
||||
{
|
||||
return parts_.cbegin();
|
||||
}
|
||||
|
||||
path::const_iterator path::cend() const
|
||||
{
|
||||
return parts_.cend();
|
||||
}
|
||||
|
||||
path::reverse_iterator path::rbegin()
|
||||
{
|
||||
return parts_.rbegin();
|
||||
}
|
||||
|
||||
path::reverse_iterator path::rend()
|
||||
{
|
||||
return parts_.rend();
|
||||
}
|
||||
|
||||
path::const_reverse_iterator path::rbegin() const
|
||||
{
|
||||
return crbegin();
|
||||
}
|
||||
|
||||
path::const_reverse_iterator path::rend() const
|
||||
{
|
||||
return crend();
|
||||
}
|
||||
|
||||
path::const_reverse_iterator path::crbegin() const
|
||||
{
|
||||
return parts_.crbegin();
|
||||
}
|
||||
|
||||
path::const_reverse_iterator path::crend() const
|
||||
{
|
||||
return parts_.crend();
|
||||
}
|
||||
|
||||
std::string path::to_hash_string() const
|
||||
{
|
||||
return to_string('/');
|
||||
return left.internal_ == right.internal_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
}
|
||||
|
||||
TS_ASSERT(!temp.get_path().exists());
|
||||
std::ofstream stream(temp.get_path().to_string());
|
||||
std::ofstream stream(temp.get_path().string());
|
||||
TS_ASSERT(temp.get_path().exists());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
{
|
||||
std::vector<std::uint8_t> buffer;
|
||||
wb.save(buffer);
|
||||
wb.save(xlnt::path("C:\\Users\\Thomas\\Desktop\\a.xlsx"));
|
||||
wb.save(xlnt::path("a.xlsx"));
|
||||
xlnt::zip_file wb_archive(buffer);
|
||||
|
||||
xlnt::zip_file file_archive(file);
|
||||
|
|
|
@ -228,8 +228,8 @@ public:
|
|||
xlnt::manifest m;
|
||||
TS_ASSERT(!m.has_default_type("xml"));
|
||||
TS_ASSERT_THROWS(m.get_default_type("xml"), xlnt::key_not_found);
|
||||
TS_ASSERT(!m.has_package_relationship(xlnt::relationship::type::office_document));
|
||||
TS_ASSERT_THROWS(m.get_part_relationships(xlnt::path("xl/workbook.xml")), xlnt::key_not_found);
|
||||
TS_ASSERT(!m.has_relationship(xlnt::path("/"), xlnt::relationship::type::office_document));
|
||||
TS_ASSERT_THROWS(m.get_relationships(xlnt::path("xl/workbook.xml")), xlnt::key_not_found);
|
||||
}
|
||||
|
||||
void test_memory()
|
||||
|
|
|
@ -68,16 +68,16 @@ workbook workbook::minimal()
|
|||
|
||||
wb.d_->manifest_.register_override_type(path("workbook.xml"),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
|
||||
wb.d_->manifest_.register_package_relationship(relationship::type::office_document,
|
||||
path("workbook.xml"), target_mode::internal);
|
||||
wb.d_->manifest_.register_relationship(uri("/"), relationship::type::office_document,
|
||||
uri("workbook.xml"), target_mode::internal);
|
||||
|
||||
std::string title("Sheet");
|
||||
wb.d_->worksheets_.push_back(detail::worksheet_impl(&wb, 1, title));
|
||||
|
||||
wb.d_->manifest_.register_override_type(path("sheet1.xml"),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
|
||||
auto ws_rel = wb.d_->manifest_.register_part_relationship(path("workbook.xml"),
|
||||
relationship::type::worksheet, path("sheet1.xml"), target_mode::internal);
|
||||
auto ws_rel = wb.d_->manifest_.register_relationship(uri("workbook.xml"),
|
||||
relationship::type::worksheet, uri("sheet1.xml"), target_mode::internal);
|
||||
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
|
||||
|
||||
return wb;
|
||||
|
@ -90,8 +90,8 @@ workbook workbook::empty_excel()
|
|||
|
||||
wb.d_->manifest_.register_override_type(path("xl/workbook.xml"),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
|
||||
wb.d_->manifest_.register_package_relationship(relationship::type::office_document,
|
||||
path("xl/workbook.xml"), target_mode::internal);
|
||||
wb.d_->manifest_.register_relationship(uri("/"), relationship::type::office_document,
|
||||
uri("xl/workbook.xml"), target_mode::internal);
|
||||
|
||||
wb.d_->manifest_.register_default_type("rels",
|
||||
"application/vnd.openxmlformats-package.relationships+xml");
|
||||
|
@ -127,13 +127,13 @@ workbook workbook::empty_excel()
|
|||
|
||||
wb.d_->manifest_.register_override_type(path("docProps/core.xml"),
|
||||
"application/vnd.openxmlformats-package.coreproperties+xml");
|
||||
wb.d_->manifest_.register_package_relationship(relationship::type::core_properties,
|
||||
path("docProps/core.xml"), target_mode::internal);
|
||||
wb.d_->manifest_.register_relationship(uri("/"), relationship::type::core_properties,
|
||||
uri("docProps/core.xml"), target_mode::internal);
|
||||
|
||||
wb.d_->manifest_.register_override_type(path("docProps/app.xml"),
|
||||
"application/vnd.openxmlformats-officedocument.extended-properties+xml");
|
||||
wb.d_->manifest_.register_package_relationship(relationship::type::extended_properties,
|
||||
path("docProps/app.xml"), target_mode::internal);
|
||||
wb.d_->manifest_.register_relationship(uri("/"), relationship::type::extended_properties,
|
||||
uri("docProps/app.xml"), target_mode::internal);
|
||||
|
||||
wb.set_application("Microsoft Excel");
|
||||
wb.create_sheet();
|
||||
|
@ -278,15 +278,15 @@ worksheet workbook::create_sheet()
|
|||
|
||||
auto sheet_id = d_->worksheets_.size() + 1;
|
||||
std::string sheet_filename = "sheet" + std::to_string(sheet_id) + ".xml";
|
||||
path sheet_path = constants::package_worksheets().append(sheet_filename);
|
||||
|
||||
d_->worksheets_.push_back(detail::worksheet_impl(this, sheet_id, title));
|
||||
|
||||
auto workbook_rel = d_->manifest_.get_package_relationship(relationship::type::office_document);
|
||||
d_->manifest_.register_override_type(sheet_path,
|
||||
auto workbook_rel = d_->manifest_.get_relationship(path("/"), relationship::type::office_document);
|
||||
uri sheet_uri(constants::package_worksheets().append(sheet_filename).string());
|
||||
d_->manifest_.register_override_type(sheet_uri.get_path(),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
|
||||
auto ws_rel = d_->manifest_.register_part_relationship(workbook_rel.get_target_uri(),
|
||||
relationship::type::worksheet, sheet_path, target_mode::internal);
|
||||
auto ws_rel = d_->manifest_.register_relationship(workbook_rel.get_target(),
|
||||
relationship::type::worksheet, sheet_uri, target_mode::internal);
|
||||
d_->sheet_title_rel_id_map_[title] = ws_rel;
|
||||
|
||||
return worksheet(&d_->worksheets_.back());
|
||||
|
@ -611,14 +611,14 @@ const theme &workbook::get_theme() const
|
|||
|
||||
void workbook::set_theme(const theme &value)
|
||||
{
|
||||
auto workbook_rel = d_->manifest_.get_package_relationship(relationship::type::office_document);
|
||||
auto workbook_rel = d_->manifest_.get_relationship(path("/"), relationship::type::office_document);
|
||||
|
||||
if (!d_->manifest_.has_part_relationship(workbook_rel.get_target_uri(), relationship::type::theme))
|
||||
if (!d_->manifest_.has_relationship(workbook_rel.get_target().get_path(), relationship::type::theme))
|
||||
{
|
||||
d_->manifest_.register_override_type(constants::part_theme(),
|
||||
"application/vnd.openxmlformats-officedocument.theme+xml");
|
||||
d_->manifest_.register_part_relationship(workbook_rel.get_target_uri(),
|
||||
relationship::type::theme, constants::part_theme(), target_mode::internal);
|
||||
d_->manifest_.register_relationship(workbook_rel.get_target(),
|
||||
relationship::type::theme, uri(constants::part_theme().string()), target_mode::internal);
|
||||
}
|
||||
|
||||
d_->has_theme_ = true;
|
||||
|
@ -642,14 +642,14 @@ std::vector<named_range> workbook::get_named_ranges() const
|
|||
|
||||
std::size_t workbook::add_format(const format &to_add)
|
||||
{
|
||||
auto workbook_rel = d_->manifest_.get_package_relationship(relationship::type::office_document);
|
||||
auto workbook_rel = d_->manifest_.get_relationship(path("/"), relationship::type::office_document);
|
||||
|
||||
if (!d_->manifest_.has_part_relationship(workbook_rel.get_target_uri(), relationship::type::styles))
|
||||
if (!d_->manifest_.has_relationship(workbook_rel.get_target().get_path(), relationship::type::styles))
|
||||
{
|
||||
d_->manifest_.register_override_type(constants::part_styles(),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
|
||||
d_->manifest_.register_part_relationship(workbook_rel.get_target_uri(),
|
||||
relationship::type::styles, constants::part_styles(), target_mode::internal);
|
||||
d_->manifest_.register_relationship(workbook_rel.get_target(),
|
||||
relationship::type::styles, uri(constants::part_styles().string()), target_mode::internal);
|
||||
}
|
||||
|
||||
return d_->stylesheet_.add_format(to_add);
|
||||
|
@ -657,14 +657,14 @@ std::size_t workbook::add_format(const format &to_add)
|
|||
|
||||
std::size_t workbook::add_style(const style &to_add)
|
||||
{
|
||||
auto workbook_rel = d_->manifest_.get_package_relationship(relationship::type::office_document);
|
||||
auto workbook_rel = d_->manifest_.get_relationship(path("/"), relationship::type::office_document);
|
||||
|
||||
if (!d_->manifest_.has_part_relationship(workbook_rel.get_target_uri(), relationship::type::styles))
|
||||
if (!d_->manifest_.has_relationship(workbook_rel.get_target().get_path(), relationship::type::styles))
|
||||
{
|
||||
d_->manifest_.register_override_type(constants::part_styles(),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
|
||||
d_->manifest_.register_part_relationship(workbook_rel.get_target_uri(),
|
||||
relationship::type::styles, constants::part_styles(), target_mode::internal);
|
||||
d_->manifest_.register_relationship(workbook_rel.get_target(),
|
||||
relationship::type::styles, uri(constants::part_styles().string()), target_mode::internal);
|
||||
}
|
||||
|
||||
return d_->stylesheet_.add_style(to_add);
|
||||
|
@ -741,14 +741,14 @@ const std::vector<text> &workbook::get_shared_strings() const
|
|||
|
||||
void workbook::add_shared_string(const text &shared, bool allow_duplicates)
|
||||
{
|
||||
auto workbook_rel = d_->manifest_.get_package_relationship(relationship::type::office_document);
|
||||
auto workbook_rel = d_->manifest_.get_relationship(path("/"), relationship::type::office_document);
|
||||
|
||||
if (!d_->manifest_.has_part_relationship(workbook_rel.get_target_uri(), relationship::type::shared_string_table))
|
||||
if (!d_->manifest_.has_relationship(workbook_rel.get_target().get_path(), relationship::type::styles))
|
||||
{
|
||||
d_->manifest_.register_override_type(constants::part_shared_strings(),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml");
|
||||
d_->manifest_.register_part_relationship(workbook_rel.get_target_uri(),
|
||||
relationship::type::shared_string_table, constants::part_shared_strings(), target_mode::internal);
|
||||
d_->manifest_.register_relationship(workbook_rel.get_target(),
|
||||
relationship::type::shared_string_table, uri(constants::part_shared_strings().string()), target_mode::internal);
|
||||
}
|
||||
|
||||
if (!allow_duplicates)
|
||||
|
@ -775,10 +775,13 @@ bool workbook::contains(const std::string &sheet_title) const
|
|||
|
||||
void workbook::set_thumbnail(const std::vector<std::uint8_t> &thumbnail,
|
||||
const std::string &extension, const std::string &content_type)
|
||||
{
|
||||
if (!d_->manifest_.has_relationship(path("/"), relationship::type::thumbnail))
|
||||
{
|
||||
d_->manifest_.register_default_type(extension, content_type);
|
||||
d_->manifest_.register_package_relationship(relationship::type::thumbnail,
|
||||
path("docProps/thumbnail.jpeg"), target_mode::internal);
|
||||
d_->manifest_.register_relationship(uri("/"), relationship::type::thumbnail,
|
||||
uri("docProps/thumbnail.jpeg"), target_mode::internal);
|
||||
}
|
||||
|
||||
d_->thumbnail_.assign(thumbnail.begin(), thumbnail.end());
|
||||
}
|
||||
|
|
|
@ -29,9 +29,8 @@ public:
|
|||
|
||||
void test_invalid_cell()
|
||||
{
|
||||
xlnt::workbook wb;
|
||||
auto ws = wb.get_active_sheet();
|
||||
TS_ASSERT_THROWS(xlnt::cell_reference invalid(xlnt::column_t((xlnt::column_t::index_t)0), 0), xlnt::invalid_cell_reference);
|
||||
TS_ASSERT_THROWS(xlnt::cell_reference(xlnt::column_t((xlnt::column_t::index_t)0), 0),
|
||||
xlnt::invalid_cell_reference);
|
||||
}
|
||||
|
||||
void test_worksheet_dimension()
|
||||
|
|
Binary file not shown.
|
@ -59,7 +59,7 @@ public:
|
|||
static xlnt::path get_data_directory(const std::string &append = "")
|
||||
{
|
||||
return xlnt::path("../../tests/data")
|
||||
.make_absolute(get_executable_directory())
|
||||
.resolve(get_executable_directory())
|
||||
.append(xlnt::path(append));
|
||||
}
|
||||
|
||||
|
@ -70,14 +70,14 @@ public:
|
|||
throw std::runtime_error("destination file already exists and overwrite==false");
|
||||
}
|
||||
|
||||
std::ifstream src(source.to_string(), std::ios::binary);
|
||||
std::ofstream dst(destination.to_string(), std::ios::binary);
|
||||
std::ifstream src(source.string(), std::ios::binary);
|
||||
std::ofstream dst(destination.string(), std::ios::binary);
|
||||
|
||||
dst << src.rdbuf();
|
||||
}
|
||||
|
||||
static void delete_file(const xlnt::path &path)
|
||||
{
|
||||
std::remove(path.to_string().c_str());
|
||||
std::remove(path.string().c_str());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -40,13 +40,13 @@ public:
|
|||
{
|
||||
if(path_.exists())
|
||||
{
|
||||
std::remove(path_.to_string().c_str());
|
||||
std::remove(path_.string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
~temporary_file()
|
||||
{
|
||||
std::remove(path_.to_string().c_str());
|
||||
std::remove(path_.string().c_str());
|
||||
}
|
||||
|
||||
xlnt::path get_path() const { return path_; }
|
||||
|
|
|
@ -135,23 +135,47 @@ public:
|
|||
auto left_info = left_archive.infolist();
|
||||
auto right_info = right_archive.infolist();
|
||||
|
||||
if (left_info.size() != right_info.size()) return false;
|
||||
if (left_info.size() != right_info.size())
|
||||
{
|
||||
std::cout << "left has a different number of files than right" << std::endl;
|
||||
|
||||
std::cout << "left has: ";
|
||||
for (auto &info : left_info)
|
||||
{
|
||||
std::cout << info.filename.string() << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "right has: ";
|
||||
for (auto &info : left_info)
|
||||
{
|
||||
std::cout << info.filename.string() << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
bool match = true;
|
||||
|
||||
for (auto left_member : left_info)
|
||||
{
|
||||
if (!right_archive.has_file(left_member)) return false;
|
||||
if (!right_archive.has_file(left_member))
|
||||
{
|
||||
match = false;
|
||||
std::cout << "right is missing file: " << left_member.filename.string() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto left_member_contents = left_archive.read(left_member);
|
||||
auto right_member_contents = right_archive.read(left_member.filename);
|
||||
|
||||
if (!strings_match(left_member_contents, right_member_contents))
|
||||
{
|
||||
std::cout << left_member.filename.to_string() << std::endl;
|
||||
return false;
|
||||
std::cout << left_member.filename.string() << std::endl;
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return match;
|
||||
}
|
||||
|
||||
static bool workbooks_match(const xlnt::workbook &left, const xlnt::workbook &right)
|
||||
|
|
Loading…
Reference in New Issue
Block a user