Comparison

teal-src/util/datamapper.tl @ 11457:6a51749af7f4

util.datamapper: Add initial support for parsing arrays
author Kim Alvefur <zash@zash.se>
date Thu, 18 Mar 2021 12:57:25 +0100
parent 11456:4e376a43fe40
child 11458:0e00fa518688
comparison
equal deleted inserted replaced
11456:4e376a43fe40 11457:6a51749af7f4
47 "in_text" 47 "in_text"
48 "in_text_tag" 48 "in_text_tag"
49 "in_attribute" 49 "in_attribute"
50 "in_single_attribute" 50 "in_single_attribute"
51 "in_children" 51 "in_children"
52 "in_wrapper"
52 end 53 end
53 54
54 local function unpack_propschema( propschema : js.schema_t | js.schema_t.type_e, propname : string, current_ns : string ) 55 local function unpack_propschema( propschema : js.schema_t | js.schema_t.type_e, propname : string, current_ns : string )
55 : js.schema_t.type_e, value_goes, string, string, string, string, { any } 56 : js.schema_t.type_e, value_goes, string, string, string, string, { any }
56 local proptype : js.schema_t.type_e = "string" 57 local proptype : js.schema_t.type_e = "string"
65 proptype = propschema.type 66 proptype = propschema.type
66 elseif propschema is js.schema_t.type_e then 67 elseif propschema is js.schema_t.type_e then
67 proptype = propschema 68 proptype = propschema
68 end 69 end
69 70
71 if proptype == "object" or proptype == "array" then
72 value_where = "in_children"
73 end
74
70 if propschema is js.schema_t then 75 if propschema is js.schema_t then
71 local xml = propschema.xml 76 local xml = propschema.xml
72 if xml then 77 if xml then
73 if xml.name then 78 if xml.name then
74 name = xml.name 79 name = xml.name
77 namespace = xml.namespace 82 namespace = xml.namespace
78 end 83 end
79 if xml.prefix then 84 if xml.prefix then
80 prefix = xml.prefix 85 prefix = xml.prefix
81 end 86 end
82 87 if proptype == "array" and xml.wrapped then
83 if xml.attribute then 88 value_where = "in_wrapper"
89 elseif xml.attribute then
84 value_where = "in_attribute" 90 value_where = "in_attribute"
85 elseif xml.text then 91 elseif xml.text then
86 value_where = "in_text" 92 value_where = "in_text"
87 elseif xml.x_name_is_value then 93 elseif xml.x_name_is_value then
88 value_where = "in_tag_name" 94 value_where = "in_tag_name"
96 elseif propschema["enum"] then 102 elseif propschema["enum"] then
97 enums = propschema["enum"] 103 enums = propschema["enum"]
98 end 104 end
99 end 105 end
100 106
101 if proptype == "object" or proptype == "array" then
102 value_where = "in_children"
103 end
104
105 return proptype, value_where, name, namespace, prefix, single_attribute, enums 107 return proptype, value_where, name, namespace, prefix, single_attribute, enums
106 end 108 end
107 109
108 110 local parse_object : function (schema : js.schema_t, s : st.stanza_t) : { string : any }
109 local function parse_object (schema : js.schema_t, s : st.stanza_t) : table 111 local parse_array : function (schema : js.schema_t, s : st.stanza_t) : { any }
112
113 function parse_object (schema : js.schema_t, s : st.stanza_t) : { string : any }
110 local out : { string : any } = {} 114 local out : { string : any } = {}
111 if schema.properties then 115 if schema.properties then
112 for prop, propschema in pairs(schema.properties) do 116 for prop, propschema in pairs(schema.properties) do
113 117
114 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) 118 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
151 if proptype == "object" then 155 if proptype == "object" then
152 local c = s:get_child(name, namespace) 156 local c = s:get_child(name, namespace)
153 if c then 157 if c then
154 out[prop] = parse_object(propschema, c); 158 out[prop] = parse_object(propschema, c);
155 end 159 end
156 -- else TODO 160 elseif proptype == "array" then
161 out[prop] = parse_array(propschema, s);
162 else
163 error "unreachable"
157 end 164 end
158 end 165 elseif value_where == "in_wrapper" and propschema is js.schema_t and proptype == "array" then
159 if value_where ~= "in_children" then 166 local wrapper = s:get_child(name, namespace);
167 if wrapper then
168 out[prop] = parse_array(propschema, wrapper);
169 else
170 error "unreachable"
171 end
172 else
173 error "unreachable"
174 end
175 if value_where ~= "in_children" and value_where ~= "in_wrapper" then
160 out[prop] = totype(proptype, value) 176 out[prop] = totype(proptype, value)
161 end 177 end
162 end 178 end
163 end 179 end
164 180
165 return out 181 return out
182 end
183
184 function parse_array (schema : js.schema_t, s : st.stanza_t) : { any }
185 local proptype, value_where, child_name, namespace = unpack_propschema(schema.items, nil, s.attr.xmlns)
186 local out : { any } = {}
187 for c in s:childtags(child_name, namespace) do
188 local value : string;
189 if value_where == "in_text_tag" then
190 value = c:get_text();
191 else
192 error "NYI"
193 end
194
195 if value ~= nil then
196 table.insert(out, value);
197 end
198 end
199 return out;
166 end 200 end
167 201
168 local function parse (schema : js.schema_t, s : st.stanza_t) : table 202 local function parse (schema : js.schema_t, s : st.stanza_t) : table
169 if schema.type == "object" then 203 if schema.type == "object" then
170 return parse_object(schema, s) 204 return parse_object(schema, s)
205 elseif schema.type == "array" then
206 return parse_array(schema, s)
207 else
208 error "top-level scalars unsupported"
171 end 209 end
172 end 210 end
173 211
174 local function unparse ( schema : js.schema_t, t : table, current_name : string, current_ns : string ) : st.stanza_t 212 local function unparse ( schema : js.schema_t, t : table, current_name : string, current_ns : string ) : st.stanza_t
175 if schema.type == "object" then 213 if schema.type == "object" then