xml_parser_util.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // ignore_for_file: implementation_imports
  2. import "package:photos/utils/multipart_upload_util.dart";
  3. import "package:xml/src/xml/entities/named_entities.dart";
  4. import "package:xml/xml.dart";
  5. // for converting the response to xml
  6. String convertJs2Xml(Map<String, dynamic> json) {
  7. final builder = XmlBuilder();
  8. buildXml(builder, json);
  9. return builder.buildDocument().toXmlString(
  10. pretty: true,
  11. indent: ' ',
  12. entityMapping: defaultMyEntityMapping,
  13. );
  14. }
  15. void buildXml(XmlBuilder builder, dynamic node) {
  16. if (node is Map<String, dynamic>) {
  17. node.forEach((key, value) {
  18. builder.element(key, nest: () => buildXml(builder, value));
  19. });
  20. } else if (node is List<dynamic>) {
  21. for (var item in node) {
  22. buildXml(builder, item);
  23. }
  24. } else if (node is PartETag) {
  25. builder.element(
  26. "Part",
  27. nest: () {
  28. builder.element(
  29. "PartNumber",
  30. nest: () {
  31. buildXml(builder, node.partNumber);
  32. },
  33. );
  34. builder.element(
  35. "ETag",
  36. nest: () {
  37. buildXml(builder, node.eTag);
  38. },
  39. );
  40. },
  41. );
  42. } else {
  43. builder.text(node.toString());
  44. }
  45. }
  46. XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml();
  47. class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping {
  48. MyXmlDefaultEntityMapping.xml() : this(xmlEntities);
  49. MyXmlDefaultEntityMapping.html() : this(htmlEntities);
  50. MyXmlDefaultEntityMapping.html5() : this(html5Entities);
  51. MyXmlDefaultEntityMapping(super.entities);
  52. @override
  53. String encodeText(String input) =>
  54. input.replaceAllMapped(_textPattern, _textReplace);
  55. @override
  56. String encodeAttributeValue(String input, XmlAttributeType type) {
  57. switch (type) {
  58. case XmlAttributeType.SINGLE_QUOTE:
  59. return input.replaceAllMapped(
  60. _singeQuoteAttributePattern,
  61. _singeQuoteAttributeReplace,
  62. );
  63. case XmlAttributeType.DOUBLE_QUOTE:
  64. return input.replaceAllMapped(
  65. _doubleQuoteAttributePattern,
  66. _doubleQuoteAttributeReplace,
  67. );
  68. }
  69. }
  70. }
  71. final _textPattern = RegExp(r'[&<>' + _highlyDiscouragedCharClass + r']');
  72. String _textReplace(Match match) {
  73. final toEscape = match.group(0)!;
  74. switch (toEscape) {
  75. case '<':
  76. return '&lt;';
  77. case '&':
  78. return '&amp;';
  79. case '>':
  80. return '&gt;';
  81. default:
  82. return _asNumericCharacterReferences(toEscape);
  83. }
  84. }
  85. final _singeQuoteAttributePattern =
  86. RegExp(r"['&<>\n\r\t" + _highlyDiscouragedCharClass + r']');
  87. String _singeQuoteAttributeReplace(Match match) {
  88. final toEscape = match.group(0)!;
  89. switch (toEscape) {
  90. case "'":
  91. return '';
  92. case '&':
  93. return '&amp;';
  94. case '<':
  95. return '&lt;';
  96. case '>':
  97. return '&gt;';
  98. default:
  99. return _asNumericCharacterReferences(toEscape);
  100. }
  101. }
  102. final _doubleQuoteAttributePattern =
  103. RegExp(r'["&<>\n\r\t' + _highlyDiscouragedCharClass + r']');
  104. String _doubleQuoteAttributeReplace(Match match) {
  105. final toEscape = match.group(0)!;
  106. switch (toEscape) {
  107. case '"':
  108. return '';
  109. case '&':
  110. return '&amp;';
  111. case '<':
  112. return '&lt;';
  113. case '>':
  114. return '&gt;';
  115. default:
  116. return _asNumericCharacterReferences(toEscape);
  117. }
  118. }
  119. const _highlyDiscouragedCharClass =
  120. r'\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f';
  121. String _asNumericCharacterReferences(String toEscape) => toEscape.runes
  122. .map((rune) => '&#x${rune.toRadixString(16).toUpperCase()};')
  123. .join();