1
2
3
4
5
6 using System;
7
8 namespace System.Xml
9 {
10 public abstract class CharacterData : Node
11 {
12 public CharacterData(NodeKind kind_, const System.Lex.Span& span_, int fileIndex_, const string& name_) : this(kind_, span_, fileIndex_, name_, string())
13 {
14 }
15 public CharacterData(NodeKind kind_, const System.Lex.Span& span_, int fileIndex_, const string& name_, const string& data_) :
16 base(kind_, span_, fileIndex_, name_), data(data_)
17 {
18 }
19 [nodiscard]
20 public override Result<bool> Write(System.Text.CodeFormatter& formatter)
21 {
22 if (formatter.Error())
23 {
24 return Result<bool>(ErrorId(formatter.GetErrorId()));
25 }
26 auto escapeValue = XmlCharDataEscape(data);
27 if (escapeValue.Error())
28 {
29 return Result<bool>(ErrorId(escapeValue.GetErrorId()));
30 }
31 formatter << escapeValue.Value();
32 return Result<bool>(true);
33 }
34 public override bool ValueContainsNewLine() const
35 {
36 return data.Find('\n') != -1;
37 }
38 public const string& Data() const
39 {
40 return data;
41 }
42 private string data;
43 }
44
45 [nodiscard]
46 public Result<string> XmlCharDataEscape(const string& text)
47 {
48 string result;
49 auto utf32Result = ToUtf32(text);
50 if (utf32Result.Error())
51 {
52 return Result<string>(ErrorId(utf32Result.GetErrorId()));
53 }
54 ustring value = utf32Result.Value();
55 for (uchar c : value)
56 {
57 switch (c)
58 {
59 case '<':
60 {
61 result.Append("<");
62 break;
63 }
64 case '&':
65 {
66 result.Append("&");
67 break;
68 }
69 case '\r': case '\n':
70 {
71 result.Append(cast<char>(c));
72 break;
73 }
74 default:
75 {
76 if (cast<int>(c) >= 32 && cast<int>(c) < 127)
77 {
78 result.Append(cast<char>(c));
79 }
80 else
81 {
82 int codePoint = cast<int>(c);
83 string charText = "&#";
84 charText.Append(ToString(codePoint)).Append(';');
85 result.Append(charText);
86 }
87 break;
88 }
89 }
90 }
91 return Result<string>(result);
92 }
93 }