Branch data TLA Line data Source code
1 : : #include <xlnt/packaging/ext_list.hpp>
2 : : #include <algorithm>
3 : :
4 : : #include <detail/external/include_libstudxml.hpp>
5 : :
6 : : namespace {
7 : : // send elements straight from parser to serialiser without modification
8 : : // runs until the end of the current open element
9 :CBC 6 : xlnt::uri roundtrip(xml::parser &p, xml::serializer &s)
10 : : {
11 : 6 : xlnt::uri ext_uri;
12 : 6 : int nest_level = 0;
13 [ + + + + : 30 : while (nest_level > 0 || (p.peek() != xml::parser::event_type::end_element && p.peek() != xml::parser::event_type::eof))
+ + + - +
+ ]
14 : : {
15 [ + + + - : 24 : switch (p.next())
- - - - ]
16 : : {
17 : 12 : case xml::parser::start_element: {
18 : 12 : ++nest_level;
19 [ + + ]: 12 : auto attribs = p.attribute_map();
20 [ + ]: 12 : s.start_element(p.qname());
21 [ + + ]: 12 : if (nest_level == 1)
22 : : {
23 [ + + + + ]: 12 : ext_uri = xlnt::uri(attribs.at(xml::qname("uri")).value);
24 : : }
25 [ + ]: 12 : auto current_ns = p.namespace_();
26 [ + ]: 12 : p.peek(); // to look into the new namespace
27 [ + ]: 12 : auto new_ns = p.namespace_(); // only before attributes?
28 [ + + ]: 12 : if (new_ns != current_ns)
29 : : {
30 [ + ]: 6 : auto pref = p.prefix();
31 [ + ]: 6 : s.namespace_decl(new_ns, pref);
32 : 6 : }
33 [ + + ]: 36 : for (auto &ele : attribs)
34 : : {
35 [ + ]: 24 : s.attribute(ele.first, ele.second.value);
36 : : }
37 : 12 : break;
38 : 12 : }
39 : 12 : case xml::parser::end_element: {
40 : 12 : --nest_level;
41 [ + ]: 12 : s.end_element();
42 : 12 : break;
43 : : }
44 :UBC 0 : case xml::parser::start_namespace_decl: {
45 [ # ]: 0 : s.namespace_decl(p.namespace_(), p.prefix());
46 : 0 : break;
47 : : }
48 : 0 : case xml::parser::end_namespace_decl: { // nothing required here
49 : 0 : break;
50 : : }
51 : 0 : case xml::parser::characters: {
52 [ # ]: 0 : s.characters(p.value());
53 : 0 : break;
54 : : }
55 : 0 : case xml::parser::eof:
56 : 0 : return ext_uri;
57 : 0 : case xml::parser::start_attribute:
58 : : case xml::parser::end_attribute:
59 : : default:
60 : 0 : break;
61 : : }
62 : : }
63 :CBC 6 : return ext_uri;
64 :UBC 0 : }
65 : : } // namespace
66 : :
67 : : namespace xlnt {
68 : :
69 :CBC 4 : ext_list::ext::ext(xml::parser &parser, const std::string &ns)
70 : : {
71 [ + ]: 4 : std::ostringstream serialisation_stream;
72 [ + + ]: 8 : xml::serializer s(serialisation_stream, "", 0);
73 [ + + + ]: 8 : s.start_element(xml::qname(ns, "wrap")); // wrapper for the xmlns declaration
74 [ + + ]: 4 : s.namespace_decl(ns, "");
75 [ + ]: 4 : extension_ID_ = roundtrip(parser, s);
76 [ + + + ]: 4 : s.end_element(xml::qname(ns, "wrap"));
77 [ + ]: 4 : serialised_value_ = serialisation_stream.str();
78 : 4 : }
79 : :
80 :UBC 0 : ext_list::ext::ext(const uri &ID, const std::string &serialised)
81 [ # ]: 0 : : extension_ID_(ID), serialised_value_(serialised)
82 : : {
83 : 0 : }
84 : :
85 :CBC 2 : void ext_list::ext::serialise(xml::serializer &serialiser, const std::string &ns)
86 : : {
87 [ + ]: 2 : std::istringstream ser(serialised_value_);
88 [ + + ]: 6 : xml::parser p(ser, "", xml::parser::receive_default);
89 [ + + + ]: 2 : p.next_expect(xml::parser::event_type::start_element, xml::qname(ns, "wrap"));
90 [ + ]: 2 : roundtrip(p, serialiser);
91 [ + + + ]: 2 : p.next_expect(xml::parser::event_type::end_element, xml::qname(ns, "wrap"));
92 : 2 : }
93 : :
94 : 4 : ext_list::ext_list(xml::parser &parser, const std::string &ns)
95 : : {
96 : : // begin with the start element already parsed
97 [ + + + ]: 8 : while (parser.peek() == xml::parser::start_element)
98 : : {
99 [ + + ]: 4 : extensions_.push_back(ext(parser, ns));
100 : : }
101 : : // end without parsing the end element
102 : 4 : }
103 : :
104 : 2 : void ext_list::serialize(xml::serializer &serialiser, const std::string &ns)
105 : : {
106 [ + + ]: 2 : serialiser.start_element(ns, "extLst");
107 [ + + ]: 4 : for (auto &ext : extensions_)
108 : : {
109 [ + ]: 2 : ext.serialise(serialiser, ns);
110 : : }
111 : 2 : serialiser.end_element();
112 : 2 : }
113 : :
114 :UBC 0 : void ext_list::add_extension(const uri &ID, const std::string &element)
115 : : {
116 [ # # ]: 0 : extensions_.push_back(ext{ID, element});
117 : 0 : }
118 : :
119 : 0 : bool ext_list::has_extension(const uri &extension_uri) const
120 : : {
121 [ # ]: 0 : return extensions_.end() != std::find_if(extensions_.begin(), extensions_.end(), [&extension_uri](const ext &ext) { return extension_uri == ext.extension_ID_; });
122 : : }
123 : :
124 : 0 : const ext_list::ext &ext_list::extension(const uri &extension_uri) const
125 : : {
126 [ # ]: 0 : return *std::find_if(extensions_.begin(), extensions_.end(),
127 : 0 : [&extension_uri](const ext &ext) { return extension_uri == ext.extension_ID_; });
128 : : }
129 : :
130 : 0 : const std::vector<ext_list::ext> &ext_list::extensions() const
131 : : {
132 : 0 : return extensions_;
133 : : }
134 : :
135 : 0 : bool ext_list::operator==(const ext_list &rhs) const
136 : : {
137 : 0 : return extensions_ == rhs.extensions_;
138 : : }
139 : :
140 : 0 : bool ext_list::operator!=(const ext_list &rhs) const
141 : : {
142 : 0 : return !(*this == rhs);
143 : : }
144 : :
145 : : } // namespace xlnt
|