Software /
code /
prosody
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 |