fix relative paths in relationships on round-trips. I really need to clean up relationship code

This commit is contained in:
Thomas Fussell 2015-10-06 10:32:52 -04:00
parent 69032289ac
commit 4001a47ec0
4 changed files with 68 additions and 27 deletions

View File

@ -115,6 +115,7 @@ public:
worksheet create_sheet(std::size_t index);
worksheet create_sheet(const std::string &title);
worksheet create_sheet(std::size_t index, const std::string &title);
worksheet create_sheet(const std::string &title, const relationship &rel);
//add
void add_sheet(worksheet worksheet);
@ -172,6 +173,8 @@ public:
std::vector<relationship> get_relationships() const;
private:
static std::size_t index_from_ws_filename(const std::string &ws_filename);
friend class worksheet;
std::shared_ptr<detail::workbook_impl> d_;
};

View File

@ -61,7 +61,7 @@ public:
static std::string write_worksheet_rels(worksheet ws);
private:
static std::string write_relationships(const std::vector<relationship> &relationships);
static std::string write_relationships(const std::vector<relationship> &relationships, const std::string &dir = "");
};
} // namespace xlnt

View File

@ -180,8 +180,9 @@ worksheet workbook::create_sheet()
}
d_->worksheets_.push_back(detail::worksheet_impl(this, title));
create_relationship("rId" + std::to_string(d_->relationships_.size() + 1), "worksheets/sheet" + std::to_string(d_->worksheets_.size()) + ".xml", relationship::type::worksheet);
return worksheet(&d_->worksheets_.back());
create_relationship("rId" + std::to_string(d_->relationships_.size() + 1), "xl/worksheets/sheet" + std::to_string(d_->worksheets_.size()) + ".xml", relationship::type::worksheet);
return worksheet(&d_->worksheets_.back());
}
void workbook::add_sheet(xlnt::worksheet worksheet)
@ -311,7 +312,7 @@ bool workbook::load(const std::string &filename)
for(auto relationship : workbook_relationships)
{
create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
}
pugi::xml_document doc;
@ -346,9 +347,18 @@ bool workbook::load(const std::string &filename)
for(auto sheet_node : sheets_node.children("sheet"))
{
std::string relation_id = sheet_node.attribute("r:id").as_string();
auto ws = create_sheet(sheet_node.attribute("name").as_string());
auto sheet_filename = get_relationship(relation_id).get_target_uri();
std::string rel_id = sheet_node.attribute("r:id").as_string();
auto rel = std::find_if(d_->relationships_.begin(), d_->relationships_.end(),
[&](relationship &rel) { return rel.get_id() == rel_id; });
if (rel == d_->relationships_.end())
{
throw std::runtime_error("relationship not found");
}
auto ws = create_sheet(sheet_node.attribute("name").as_string(), *rel);
auto sheet_filename = rel->get_target_uri();
xlnt::reader::read_worksheet(ws, f.read(sheet_filename).c_str(), shared_strings, number_format_ids);
}
@ -400,14 +410,29 @@ worksheet workbook::create_sheet(std::size_t index)
{
create_sheet();
if(index != d_->worksheets_.size())
{
std::swap(d_->worksheets_[index], d_->worksheets_.back());
}
if (index != d_->worksheets_.size() - 1)
{
std::swap(d_->worksheets_.back(), d_->worksheets_[index]);
d_->worksheets_.pop_back();
}
return worksheet(&d_->worksheets_[index]);
}
worksheet workbook::create_sheet(const std::string &title, const relationship &rel)
{
d_->worksheets_.push_back(detail::worksheet_impl(this, title));
auto index = index_from_ws_filename(rel.get_target_uri());
if (index != d_->worksheets_.size() - 1)
{
std::swap(d_->worksheets_.back(), d_->worksheets_[index]);
d_->worksheets_.pop_back();
}
return worksheet(&d_->worksheets_[index]);
}
worksheet workbook::create_sheet(std::size_t index, const std::string &title)
{
auto ws = create_sheet(index);
@ -554,19 +579,9 @@ bool workbook::save(const std::string &filename)
{
if(relationship.get_type() == relationship::type::worksheet)
{
std::string sheet_index_string = relationship.get_target_uri();
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
auto iter = sheet_index_string.end();
iter--;
while (isdigit(*iter)) iter--;
auto first_digit = iter - sheet_index_string.begin();
sheet_index_string = sheet_index_string.substr(first_digit + 1);
auto sheet_index = std::stoi(sheet_index_string) - 1;
auto sheet_index = index_from_ws_filename(relationship.get_target_uri());
auto ws = get_sheet_by_index(sheet_index);
std::string sheet_uri = "xl/" + relationship.get_target_uri();
f.writestr(sheet_uri, writer::write_worksheet(ws, shared_strings));
f.writestr(relationship.get_target_uri(), writer::write_worksheet(ws, shared_strings));
}
}
@ -665,4 +680,18 @@ void workbook::set_data_only(bool data_only)
d_->data_only_ = data_only;
}
std::size_t workbook::index_from_ws_filename(const std::string &ws_filename)
{
std::string sheet_index_string(ws_filename);
sheet_index_string = sheet_index_string.substr(0, sheet_index_string.find('.'));
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
auto iter = sheet_index_string.end();
iter--;
while (isdigit(*iter)) iter--;
auto first_digit = iter - sheet_index_string.begin();
sheet_index_string = sheet_index_string.substr(first_digit + 1);
auto sheet_index = std::stoi(sheet_index_string) - 1;
return sheet_index;
}
}

View File

@ -123,7 +123,7 @@ std::string writer::write_properties_app(const workbook &wb)
std::string writer::write_workbook_rels(const workbook &wb)
{
return write_relationships(wb.get_relationships());
return write_relationships(wb.get_relationships(), "xl/");
}
std::string writer::write_worksheet_rels(worksheet ws)
@ -131,7 +131,6 @@ std::string writer::write_worksheet_rels(worksheet ws)
return write_relationships(ws.get_relationships());
}
std::string writer::write_workbook(const workbook &wb)
{
pugi::xml_document doc;
@ -571,18 +570,28 @@ std::string xlnt::writer::write_root_rels()
return write_relationships(relationships);
}
std::string writer::write_relationships(const std::vector<relationship> &relationships)
std::string writer::write_relationships(const std::vector<relationship> &relationships, const std::string &dir)
{
pugi::xml_document doc;
auto root_node = doc.append_child("Relationships");
root_node.append_attribute("xmlns").set_value(constants::Namespaces.at("relationships").c_str());
for(auto relationship : relationships)
{
auto target = relationship.get_target_uri();
if (dir != "" && target.substr(0, dir.size()) == dir)
{
target = target.substr(dir.size());
}
auto app_props_node = root_node.append_child("Relationship");
app_props_node.append_attribute("Id").set_value(relationship.get_id().c_str());
app_props_node.append_attribute("Target").set_value(relationship.get_target_uri().c_str());
app_props_node.append_attribute("Target").set_value(target.c_str());
app_props_node.append_attribute("Type").set_value(relationship.get_type_string().c_str());
if(relationship.get_target_mode() == target_mode::external)
{
app_props_node.append_attribute("TargetMode").set_value("External");