Comparison

teal-src/util/datamapper.tl @ 11465:19a88b61ab4e

util.datamapper: Factor out extraction of the XML part to use So extract_value() takes an XML tag and details about which part we're interested in and returns that. Factoring this out will help with array implementation since this will be common behavior.
author Kim Alvefur <zash@zash.se>
date Sat, 20 Mar 2021 19:02:18 +0100
parent 11464:6e25409fecbd
child 11466:c098d07e6717
comparison
equal deleted inserted replaced
11464:6e25409fecbd 11465:19a88b61ab4e
113 end 113 end
114 114
115 local parse_object : function (schema : schema_t, s : st.stanza_t) : { string : any } 115 local parse_object : function (schema : schema_t, s : st.stanza_t) : { string : any }
116 local parse_array : function (schema : schema_t, s : st.stanza_t) : { any } 116 local parse_array : function (schema : schema_t, s : st.stanza_t) : { any }
117 117
118 local function extract_value (s : st.stanza_t, value_where : value_goes, proptype : json.json_type_name, name : string, namespace : string, prefix : string, single_attribute : string, enums : { any }) : string
119 if value_where == "in_tag_name" then
120 local c : st.stanza_t
121 if proptype == "boolean" then
122 c = s:get_child(name, namespace);
123 elseif enums and proptype == "string" then
124 -- XXX O(n²) ?
125 -- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
126 -- BUT works first, optimize later
127 for i = 1, #enums do
128 c = s:get_child(enums[i] as string, namespace);
129 if c then break end
130 end
131 else
132 c = s:get_child(nil, namespace);
133 end
134 if c then
135 return c.name;
136 end
137 elseif value_where == "in_attribute" then
138 local attr = name
139 if prefix then
140 attr = prefix .. ':' .. name
141 elseif namespace ~= s.attr.xmlns then
142 attr = namespace .. "\1" .. name
143 end
144 return s.attr[attr]
145
146 elseif value_where == "in_text" then
147 return s:get_text()
148
149 elseif value_where == "in_single_attribute" then
150 local c = s:get_child(name, namespace)
151 return c and c.attr[single_attribute]
152 elseif value_where == "in_text_tag" then
153 return s:get_child_text(name, namespace)
154 end
155 end
156
118 function parse_object (schema : schema_t, s : st.stanza_t) : { string : any } 157 function parse_object (schema : schema_t, s : st.stanza_t) : { string : any }
119 local out : { string : any } = {} 158 local out : { string : any } = {}
120 if schema is json_schema_object and schema.properties then 159 if schema is json_schema_object and schema.properties then
121 for prop, propschema in pairs(schema.properties) do 160 for prop, propschema in pairs(schema.properties) do
122 161
123 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) 162 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
124 163
125 local value : string 164 if value_where == "in_children" and propschema is json_schema_object then
126 if value_where == "in_tag_name" then
127 local c : st.stanza_t
128 if proptype == "boolean" then
129 c = s:get_child(name, namespace);
130 elseif enums and proptype == "string" then
131 -- XXX O(n²) ?
132 -- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
133 -- BUT works first, optimize later
134 for i = 1, #enums do
135 c = s:get_child(enums[i] as string, namespace);
136 if c then break end
137 end
138 else
139 c = s:get_child(nil, namespace);
140 end
141 if c is st.stanza_t then
142 value = c.name;
143 end
144 elseif value_where == "in_attribute" then
145 local attr = name
146 if prefix then
147 attr = prefix .. ':' .. name
148 elseif namespace ~= s.attr.xmlns then
149 attr = namespace .. "\1" .. name
150 end
151 value = s.attr[attr]
152
153 elseif value_where == "in_text" then
154 value = s:get_text()
155
156 elseif value_where == "in_single_attribute" then
157 local c = s:get_child(name, namespace)
158 value = c and c.attr[single_attribute]
159 elseif value_where == "in_text_tag" then
160 value = s:get_child_text(name, namespace)
161 elseif value_where == "in_children" and propschema is json_schema_object then
162 if proptype == "object" then 165 if proptype == "object" then
163 local c = s:get_child(name, namespace) 166 local c = s:get_child(name, namespace)
164 if c then 167 if c then
165 out[prop] = parse_object(propschema, c); 168 out[prop] = parse_object(propschema, c);
166 end 169 end
175 out[prop] = parse_array(propschema, wrapper); 178 out[prop] = parse_array(propschema, wrapper);
176 else 179 else
177 error "unreachable" 180 error "unreachable"
178 end 181 end
179 else 182 else
180 error "unreachable" 183 local value : string = extract_value (s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
181 end 184
182 if value_where ~= "in_children" and value_where ~= "in_wrapper" then
183 out[prop] = totype(proptype, value) 185 out[prop] = totype(proptype, value)
184 end 186 end
185 end 187 end
186 end 188 end
187 189