1use std::collections::HashMap;
5use std::fmt;
6use std::fmt::Formatter;
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct XMLDecl {
10 pub(crate) version: String,
11 pub(crate) encoding: Option<String>,
12 pub(crate) standalone: Option<String>,
13}
14
15impl XMLDecl {
16 pub fn new(version: String, encoding: Option<String>, standalone: Option<String>) -> Self {
17 XMLDecl {
18 version,
19 encoding,
20 standalone,
21 }
22 }
23 pub fn version(&self) -> String {
24 self.version.clone()
25 }
26 pub fn set_encoding(&mut self, e: String) {
27 self.encoding = Some(e)
28 }
29 pub fn encoding(&self) -> String {
30 self.encoding.as_ref().map_or(String::new(), |e| e.clone())
31 }
32 pub fn set_standalone(&mut self, s: String) {
33 self.standalone = Some(s)
34 }
35 pub fn standalone(&self) -> String {
36 self.standalone
37 .as_ref()
38 .map_or(String::new(), |e| e.clone())
39 }
40}
41
42impl fmt::Display for XMLDecl {
43 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
44 let mut result = String::from("<?xml version=\"");
45 result.push_str(self.version.as_str());
46 result.push('"');
47 if let Some(e) = self.encoding.as_ref() {
48 result.push_str(" encoding=\"");
49 result.push_str(e.as_str());
50 result.push('"');
51 };
52 if let Some(e) = self.standalone.as_ref() {
53 result.push_str(" standalone=\"");
54 result.push_str(e.as_str());
55 result.push('"');
56 };
57 f.write_str(result.as_str())
58 }
59}
60
61pub struct XMLDeclBuilder(XMLDecl);
62
63impl Default for XMLDeclBuilder {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69impl XMLDeclBuilder {
70 pub fn new() -> Self {
71 XMLDeclBuilder(XMLDecl {
72 version: String::new(),
73 encoding: None,
74 standalone: None,
75 })
76 }
77 pub fn version(mut self, v: String) -> Self {
78 self.0.version = v;
79 self
80 }
81 pub fn encoding(mut self, v: String) -> Self {
82 self.0.encoding = Some(v);
83 self
84 }
85 pub fn standalone(mut self, v: String) -> Self {
86 self.0.standalone = Some(v);
87 self
88 }
89 pub fn build(self) -> XMLDecl {
90 self.0
91 }
92}
93
94#[derive(Clone, PartialEq, Debug)]
101pub struct DTD {
102 pub(crate) elements: HashMap<(Option<String>, String), DTDPattern>,
105 pub(crate) attlists: HashMap<
106 (Option<String>, String),
107 HashMap<(Option<String>, String), (AttType, DefaultDecl, bool)>,
108 >, pub(crate) notations: HashMap<String, DTDDecl>,
110 pub(crate) generalentities: HashMap<String, (String, bool)>, pub(crate) paramentities: HashMap<String, (String, bool)>, publicid: Option<String>,
113 systemid: Option<String>,
114 pub(crate) name: Option<(Option<String>, String)>,
115 pub(crate) patterns: HashMap<(Option<String>, String), DTDPattern>,
116}
117
118impl DTD {
119 pub fn new() -> DTD {
120 let default_entities = vec![
121 ("amp".to_string(), ("&".to_string(), false)),
122 ("gt".to_string(), (">".to_string(), false)),
123 ("lt".to_string(), ("<".to_string(), false)),
124 ("apos".to_string(), ("'".to_string(), false)),
125 ("quot".to_string(), ("\"".to_string(), false)),
126 ];
127 DTD {
128 elements: Default::default(),
129 attlists: Default::default(),
130 notations: Default::default(),
131 generalentities: default_entities.into_iter().collect(),
132 paramentities: HashMap::new(),
133 publicid: None,
134 systemid: None,
135 name: None,
136 patterns: HashMap::new(),
137 }
138 }
139}
140
141impl Default for DTD {
142 fn default() -> Self {
143 Self::new()
144 }
145}
146
147#[derive(Clone, Debug, Eq, PartialEq)]
148pub enum DTDDecl {
149 Notation((Option<String>, String), String),
150 GeneralEntity((Option<String>, String), String),
151 ParamEntity((Option<String>, String), String),
152}
153
154#[allow(clippy::upper_case_acronyms)]
155#[derive(Clone, Debug, Eq, PartialEq)]
156pub(crate) enum AttType {
157 CDATA,
158 ID,
159 IDREF,
160 IDREFS,
161 ENTITY,
162 ENTITIES,
163 NMTOKEN,
164 NMTOKENS,
165 NOTATION(Vec<String>),
166 ENUMERATION(Vec<String>),
167}
168
169#[allow(clippy::upper_case_acronyms)]
170#[derive(Clone, Debug, Eq, PartialEq)]
171pub(crate) enum DefaultDecl {
172 Required,
173 Implied,
174 FIXED(String),
175 Default(String),
176}
177
178#[derive(Clone, PartialEq, Debug)]
179pub(crate) enum DTDPattern {
180 Choice(Box<DTDPattern>, Box<DTDPattern>),
181 Interleave(Box<DTDPattern>, Box<DTDPattern>),
182 Group(Box<DTDPattern>, Box<DTDPattern>),
183 OneOrMore(Box<DTDPattern>),
184 After(Box<DTDPattern>, Box<DTDPattern>),
185 Empty,
186 NotAllowed,
187 Text,
188 Value(String),
189 Attribute((Option<String>, String), Box<DTDPattern>),
190 Element((Option<String>, String), Box<DTDPattern>),
191 Ref((Option<String>, String)),
192 Any,
193 #[allow(dead_code)]
197 List(Box<DTDPattern>),
198}