1 // Copyright (c) 2018
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE
20 //
21 // @license: http://www.opensource.org/licenses/mit-license.php
22 // @author: see AUTHORS file
23
24 #include <xlnt/drawing/spreadsheet_drawing.hpp>
25 #include <detail/constants.hpp>
26
27 #include <detail/external/include_libstudxml.hpp>
28
29 namespace {
30 // copy elements to the serializer provided and extract the embed ids
31 // from blip elements
copy_and_extract(xml::parser & p,xml::serializer & s)32 std::vector<std::string> copy_and_extract(xml::parser &p, xml::serializer &s)
33 {
34 std::vector<std::string> embed_ids;
35 int nest_level = 0;
36 while (nest_level > 0 || (p.peek() != xml::parser::event_type::end_element && p.peek() != xml::parser::event_type::eof))
37 {
38 switch (p.next())
39 {
40 case xml::parser::start_element: {
41 ++nest_level;
42 auto attribs = p.attribute_map();
43 auto current_ns = p.namespace_();
44 s.start_element(p.qname());
45 s.namespace_decl(current_ns, p.prefix());
46 if (p.qname().name() == "blip")
47 {
48 embed_ids.push_back(attribs.at(xml::qname(xlnt::constants::ns("r"), "embed")).value);
49 }
50 p.peek();
51 auto new_ns = p.namespace_();
52 if (new_ns != current_ns)
53 {
54 auto pref = p.prefix();
55 s.namespace_decl(new_ns, pref);
56 }
57 for (auto &ele : attribs)
58 {
59 s.attribute(ele.first, ele.second.value);
60 }
61 break;
62 }
63 case xml::parser::end_element: {
64 --nest_level;
65 s.end_element();
66 break;
67 }
68 case xml::parser::start_namespace_decl: {
69 s.namespace_decl(p.namespace_(), p.prefix());
70 break;
71 }
72 case xml::parser::end_namespace_decl: { // nothing required here
73 break;
74 }
75 case xml::parser::characters: {
76 s.characters(p.value());
77 break;
78 }
79 case xml::parser::eof:
80 return embed_ids;
81 case xml::parser::start_attribute:
82 case xml::parser::end_attribute:
83 default:
84 break;
85 }
86 }
87 return embed_ids;
88 }
89 } // namespace
90
91 namespace xlnt {
92 namespace drawing {
93
spreadsheet_drawing(xml::parser & parser)94 spreadsheet_drawing::spreadsheet_drawing(xml::parser &parser)
95 {
96 std::ostringstream serialization_stream;
97 xml::serializer s(serialization_stream, "", 0);
98 embed_ids_ = copy_and_extract(parser, s);
99 serialized_value_ = serialization_stream.str();
100 }
101
102 // void spreadsheet_drawing::serialize(xml::serializer &serializer, const std::string& ns)
serialize(xml::serializer & serializer)103 void spreadsheet_drawing::serialize(xml::serializer &serializer)
104 {
105 std::istringstream ser(serialized_value_);
106 xml::parser p(ser, "", xml::parser::receive_default);
107 copy_and_extract(p, serializer);
108 }
109
get_embed_ids()110 std::vector<std::string> spreadsheet_drawing::get_embed_ids()
111 {
112 return embed_ids_;
113 }
114
115 } // namespace drawing
116 } // namespace xlnt
117