ext_list.cpp 4.1 KB

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