Template.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #include "Template.h"
  2. #include "../../Include/RmlUi/Core/Element.h"
  3. #include "../../Include/RmlUi/Core/ElementUtilities.h"
  4. #include "../../Include/RmlUi/Core/XMLParser.h"
  5. #include "XMLParseTools.h"
  6. #include <string.h>
  7. namespace Rml {
  8. Template::Template() {}
  9. Template::~Template() {}
  10. const String& Template::GetName() const
  11. {
  12. return name;
  13. }
  14. bool Template::Load(Stream* stream)
  15. {
  16. // Load the entire template into memory so we can pull out
  17. // the header and body tags
  18. String buffer;
  19. stream->Read(buffer, stream->Length());
  20. // Pull out the header
  21. const char* head_start = XMLParseTools::FindTag("head", buffer.c_str());
  22. if (!head_start)
  23. return false;
  24. const char* head_end = XMLParseTools::FindTag("head", head_start, true);
  25. if (!head_end)
  26. return false;
  27. // Advance to the end of the tag
  28. head_end = strchr(head_end, '>') + 1;
  29. // Pull out the body
  30. const char* body_start = XMLParseTools::FindTag("body", head_end);
  31. if (!body_start)
  32. return false;
  33. const char* body_end = XMLParseTools::FindTag("body", body_start, true);
  34. if (!body_end)
  35. return false;
  36. // Advance to the end of the tag
  37. body_end = strchr(body_end, '>') + 1;
  38. // Find the RML tag, skip over it and read the attributes,
  39. // storing the ones we're interested in.
  40. String attribute_name;
  41. String attribute_value;
  42. const char* ptr = XMLParseTools::FindTag("template", buffer.c_str());
  43. if (!ptr)
  44. return false;
  45. while (XMLParseTools::ReadAttribute(++ptr, attribute_name, attribute_value))
  46. {
  47. if (attribute_name == "name")
  48. name = attribute_value;
  49. if (attribute_name == "content")
  50. content = attribute_value;
  51. }
  52. // Create a stream around the header, parse it and store it
  53. auto header_stream = MakeUnique<StreamMemory>((const byte*)head_start, head_end - head_start);
  54. header_stream->SetSourceURL(stream->GetSourceURL());
  55. XMLParser parser(nullptr);
  56. parser.Parse(header_stream.get());
  57. header_stream.reset();
  58. header = *parser.GetDocumentHeader();
  59. // Store the body in stream form
  60. body = MakeUnique<StreamMemory>(body_end - body_start);
  61. body->SetSourceURL(stream->GetSourceURL());
  62. body->PushBack(body_start, body_end - body_start);
  63. return true;
  64. }
  65. Element* Template::ParseTemplate(Element* element)
  66. {
  67. body->Seek(0, SEEK_SET);
  68. const int num_children_before = element->GetNumChildren();
  69. XMLParser parser(element);
  70. parser.Parse(body.get());
  71. // If there's an inject attribute on the template, attempt to find the required element.
  72. if (!content.empty())
  73. {
  74. const int num_children_after = element->GetNumChildren();
  75. // We look through the newly added elements (and only those), and look for the desired id.
  76. for (int i = num_children_before; i < num_children_after; ++i)
  77. {
  78. Element* content_element = ElementUtilities::GetElementById(element->GetChild(i), content);
  79. if (content_element)
  80. {
  81. element = content_element;
  82. break;
  83. }
  84. }
  85. }
  86. return element;
  87. }
  88. const DocumentHeader* Template::GetHeader()
  89. {
  90. return &header;
  91. }
  92. } // namespace Rml