mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
parse relationship mode and implement reading hyperlinks, closes #87
This commit is contained in:
parent
d9b1fef34f
commit
a1ff8c0ed2
|
@ -368,6 +368,20 @@ struct value_traits<xlnt::border_side>
|
||||||
}
|
}
|
||||||
}; // struct value_traits<xlnt::border_side>
|
}; // struct value_traits<xlnt::border_side>
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct value_traits<xlnt::target_mode>
|
||||||
|
{
|
||||||
|
static xlnt::target_mode parse(std::string mode_string, const parser &)
|
||||||
|
{
|
||||||
|
return mode_string == "Internal" ? xlnt::target_mode::internal : xlnt::target_mode::external;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string serialize (xlnt::target_mode mode, const serializer &)
|
||||||
|
{
|
||||||
|
return mode == xlnt::target_mode::internal ? "Internal" : "External";
|
||||||
|
}
|
||||||
|
}; // struct value_traits<xlnt::target_mode>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ struct hash<xml::qname>
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#error NDEBUG
|
|
||||||
#define THROW_ON_INVALID_XML
|
#define THROW_ON_INVALID_XML
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -160,10 +159,15 @@ std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
|
||||||
while (in_element(xml::qname(xmlns, "Relationships")))
|
while (in_element(xml::qname(xmlns, "Relationships")))
|
||||||
{
|
{
|
||||||
expect_start_element(xml::qname(xmlns, "Relationship"), xml::content::simple);
|
expect_start_element(xml::qname(xmlns, "Relationship"), xml::content::simple);
|
||||||
|
|
||||||
|
auto mode = parser.attribute_present("TargetMode")
|
||||||
|
? parser.attribute<xlnt::target_mode>("TargetMode")
|
||||||
|
: target_mode::internal;
|
||||||
relationships.emplace_back(parser.attribute("Id"),
|
relationships.emplace_back(parser.attribute("Id"),
|
||||||
parser.attribute<xlnt::relationship::type>("Type"), source,
|
parser.attribute<xlnt::relationship::type>("Type"), source,
|
||||||
xlnt::uri(parser.attribute("Target")),
|
xlnt::uri(parser.attribute("Target")),
|
||||||
xlnt::target_mode::internal);
|
mode);
|
||||||
|
|
||||||
expect_end_element(xml::qname(xmlns, "Relationship"));
|
expect_end_element(xml::qname(xmlns, "Relationship"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1567,6 +1571,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||||
static const auto &xmlns = constants::get_namespace("spreadsheetml");
|
static const auto &xmlns = constants::get_namespace("spreadsheetml");
|
||||||
static const auto &xmlns_mc = constants::get_namespace("mc");
|
static const auto &xmlns_mc = constants::get_namespace("mc");
|
||||||
static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
|
static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
|
||||||
|
static const auto &xmlns_r = constants::get_namespace("r");
|
||||||
|
|
||||||
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
|
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
|
||||||
target_.d_->sheet_title_rel_id_map_.end(),
|
target_.d_->sheet_title_rel_id_map_.end(),
|
||||||
|
@ -1596,7 +1601,14 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||||
skip_attributes({xml::qname(xmlns_mc, "Ignorable")});
|
skip_attributes({xml::qname(xmlns_mc, "Ignorable")});
|
||||||
|
|
||||||
xlnt::range_reference full_range;
|
xlnt::range_reference full_range;
|
||||||
|
|
||||||
const auto &shared_strings = target_.get_shared_strings();
|
const auto &shared_strings = target_.get_shared_strings();
|
||||||
|
auto &manifest = target_.get_manifest();
|
||||||
|
|
||||||
|
const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document);
|
||||||
|
const auto sheet_rel = manifest.get_relationship(workbook_rel.get_target().get_path(), rel_id);
|
||||||
|
path sheet_path(sheet_rel.get_source().get_path().parent().append(sheet_rel.get_target().get_path()));
|
||||||
|
auto hyperlinks = manifest.get_relationships(sheet_path, xlnt::relationship::type::hyperlink);
|
||||||
|
|
||||||
while (in_element(xml::qname(xmlns, "worksheet")))
|
while (in_element(xml::qname(xmlns, "worksheet")))
|
||||||
{
|
{
|
||||||
|
@ -1853,7 +1865,22 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||||
}
|
}
|
||||||
else if (current_worksheet_element == xml::qname(xmlns, "hyperlinks")) // CT_Hyperlinks 0-1
|
else if (current_worksheet_element == xml::qname(xmlns, "hyperlinks")) // CT_Hyperlinks 0-1
|
||||||
{
|
{
|
||||||
skip_remaining_content(current_worksheet_element);
|
while (in_element(xml::qname(xmlns, "hyperlinks")))
|
||||||
|
{
|
||||||
|
expect_start_element(xml::qname(xmlns, "hyperlink"), xml::content::simple);
|
||||||
|
|
||||||
|
auto cell = ws.get_cell(parser().attribute("ref"));
|
||||||
|
auto hyperlink_rel_id = parser().attribute(xml::qname(xmlns_r, "id"));
|
||||||
|
auto hyperlink_rel = std::find_if(hyperlinks.begin(), hyperlinks.end(),
|
||||||
|
[&](const relationship &r) { return r.get_id() == hyperlink_rel_id; });
|
||||||
|
|
||||||
|
if (hyperlink_rel != hyperlinks.end())
|
||||||
|
{
|
||||||
|
cell.set_hyperlink(hyperlink_rel->get_target().get_path().string());
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_end_element(xml::qname(xmlns, "hyperlink"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (current_worksheet_element == xml::qname(xmlns, "printOptions")) // CT_PrintOptions 0-1
|
else if (current_worksheet_element == xml::qname(xmlns, "printOptions")) // CT_PrintOptions 0-1
|
||||||
{
|
{
|
||||||
|
@ -1922,11 +1949,6 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
||||||
|
|
||||||
expect_end_element(xml::qname(xmlns, "worksheet"));
|
expect_end_element(xml::qname(xmlns, "worksheet"));
|
||||||
|
|
||||||
auto &manifest = target_.get_manifest();
|
|
||||||
const auto workbook_rel = manifest.get_relationship(path("/"), relationship::type::office_document);
|
|
||||||
const auto sheet_rel = manifest.get_relationship(workbook_rel.get_target().get_path(), rel_id);
|
|
||||||
path sheet_path(sheet_rel.get_source().get_path().parent().append(sheet_rel.get_target().get_path()));
|
|
||||||
|
|
||||||
if (manifest.has_relationship(sheet_path, xlnt::relationship::type::comments))
|
if (manifest.has_relationship(sheet_path, xlnt::relationship::type::comments))
|
||||||
{
|
{
|
||||||
auto comments_part = manifest.canonicalize(
|
auto comments_part = manifest.canonicalize(
|
||||||
|
|
|
@ -106,6 +106,8 @@ std::vector<relationship> manifest::get_relationships(const path &part, relation
|
||||||
{
|
{
|
||||||
std::vector<relationship> matches;
|
std::vector<relationship> matches;
|
||||||
|
|
||||||
|
if (has_relationship(part, type))
|
||||||
|
{
|
||||||
for (const auto &rel : relationships_.at(part))
|
for (const auto &rel : relationships_.at(part))
|
||||||
{
|
{
|
||||||
if (rel.second.get_type() == type)
|
if (rel.second.get_type() == type)
|
||||||
|
@ -113,6 +115,7 @@ std::vector<relationship> manifest::get_relationships(const path &part, relation
|
||||||
matches.push_back(rel.second);
|
matches.push_back(rel.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,4 +79,13 @@ public:
|
||||||
TS_ASSERT_EQUALS(wb2.get_active_sheet().get_cell("A1").get_value<std::string>(), "unicode!");
|
TS_ASSERT_EQUALS(wb2.get_active_sheet().get_cell("A1").get_value<std::string>(), "unicode!");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_read_hyperlink()
|
||||||
|
{
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.load("data/20_with_hyperlink.xlsx");
|
||||||
|
TS_ASSERT(wb.get_active_sheet().get_cell("A1").has_hyperlink());
|
||||||
|
TS_ASSERT_EQUALS(wb.get_active_sheet().get_cell("A1").get_hyperlink(),
|
||||||
|
"https://fr.wikipedia.org/wiki/Ille-et-Vilaine");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
BIN
tests/data/20_with_hyperlink.xlsx
Normal file
BIN
tests/data/20_with_hyperlink.xlsx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user