Simple XML subset parser comparable to glib's Markup parser, but without any dependencies in one self contained file. Forked from https://github.com/ooxi/xml.c
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * Copyright (c) 2012 ooxi/xml.c
  3. * https://github.com/ooxi/xml.c
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * In no event will the authors be held liable for any damages arising from the
  7. * use of this software.
  8. *
  9. * Permission is granted to anyone to use this software for any purpose,
  10. * including commercial applications, and to alter it and redistribute it
  11. * freely, subject to the following restrictions:
  12. *
  13. * 1. The origin of this software must not be misrepresented; you must not
  14. * claim that you wrote the original software. If you use this software in a
  15. * product, an acknowledgment in the product documentation would be
  16. * appreciated but is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such, and must not be
  19. * misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any source distribution.
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <xml.h>
  26. static _Bool true = 1;
  27. static _Bool false = 0;
  28. /**
  29. * Will halt the program iff assertion fails
  30. */
  31. static void _assert_that(_Bool condition, char const* message, char const* func, char const* file, int line) {
  32. if (!condition) {
  33. fprintf(stderr, "Assertion failed: %s, in %s (%s:%i)\n", message, func, file, line);
  34. exit(EXIT_FAILURE);
  35. }
  36. }
  37. #define assert_that(condition, message) \
  38. _assert_that(condition, message, __func__, __FILE__, __LINE__)
  39. /**
  40. * @return true iff xml string equals the c string
  41. */
  42. static _Bool string_equals(struct xml_string* a, char const* b) {
  43. size_t a_length = xml_string_length(a);
  44. size_t b_length = strlen(b);
  45. uint8_t* a_buffer = alloca((a_length + 1) * sizeof(uint8_t));
  46. xml_string_copy(a, a_buffer, a_length);
  47. a_buffer[a_length] = 0;
  48. if (a_length != b_length) {
  49. fprintf(stderr, "string_equals: %s#%i <> %s#%i\n", a_buffer, (int)a_length, b, (int)b_length);
  50. return false;
  51. }
  52. size_t i = 0; for (; i < a_length; ++i) {
  53. if (a_buffer[i] != b[i]) {
  54. fprintf(stderr, "string_equals: %s <> %s\n", a_buffer, b);
  55. return false;
  56. }
  57. }
  58. return true;
  59. }
  60. /**
  61. * Converts a static character array to an uint8_t data source
  62. */
  63. #define SOURCE(source, content) \
  64. uint8_t* source = alloca(strlen(content) * sizeof(uint8_t)); \
  65. { size_t i = 0; for (; i < strlen(content); ++i) { \
  66. source[i] = content[i]; \
  67. } \
  68. }
  69. /**
  70. * Tries to parse a simple document containing only one tag
  71. */
  72. static void test_xml_parse_document_0() {
  73. SOURCE(source, "<Hello>World</Hello>");
  74. struct xml_document* document = xml_parse_document(source, strlen(source));
  75. assert_that(document, "Could not parse document");
  76. struct xml_node* root = xml_document_root(document);
  77. assert_that(string_equals(xml_node_name(root), "Hello"), "root node name must be `Hello'");
  78. assert_that(string_equals(xml_node_content(root), "World"), "root node content must be `World'");
  79. xml_document_free(document, false);
  80. }
  81. /**
  82. * Tries to parse a document containing multiple tags
  83. */
  84. static void test_xml_parse_document_1() {
  85. SOURCE(source, ""
  86. "<Parent>\n"
  87. "\t<Child>\n"
  88. "\t\tFirst content\n"
  89. "\t</Child>\n"
  90. "\t<Child>\n"
  91. "\t\tSecond content\n"
  92. "\t</Child>\n"
  93. "</Parent>\n"
  94. );
  95. struct xml_document* document = xml_parse_document(source, strlen(source));
  96. assert_that(document, "Could not parse document");
  97. struct xml_node* root = xml_document_root(document);
  98. assert_that(string_equals(xml_node_name(root), "Parent"), "root node name must be `Parent'");
  99. assert_that(2 == xml_node_children(root), "root must have two children");
  100. struct xml_node* first_child = xml_node_child(root, 0);
  101. struct xml_node* second_child = xml_node_child(root, 1);
  102. assert_that(first_child && second_child, "Failed retrieving the children of root");
  103. struct xml_node* third_child = xml_node_child(root, 2);
  104. assert_that(!third_child, "root has a third child where non should be");
  105. assert_that(string_equals(xml_node_name(first_child), "Child"), "first_child node name must be `Child'");
  106. assert_that(string_equals(xml_node_content(first_child), "First content"), "first_child node content must be `First content'");
  107. assert_that(string_equals(xml_node_name(second_child), "Child"), "second_child node name must be `Child'");
  108. assert_that(string_equals(xml_node_content(second_child), "Second content"), "second_child node content must be `tSecond content'");
  109. xml_document_free(document, false);
  110. }
  111. /**
  112. * Console interface
  113. */
  114. int main(int argc, char** argv) {
  115. test_xml_parse_document_0();
  116. test_xml_parse_document_1();
  117. fprintf(stdout, "All tests passed :-)\n");
  118. exit(EXIT_SUCCESS);
  119. }