|
1 | 1 | # Custom Function Reference
|
| 2 | + |
| 3 | +## Global `custom_func` Available to All Extensions and Versions of Schema Handlers |
| 4 | + |
| 5 | +> ### coalesce |
| 6 | +
|
| 7 | +**Synopsis**: `coalesce` returns the first non-empty string of the input strings. If no input |
| 8 | +strings are given or all of them are empty, then empty string is returned. Note: a blank |
| 9 | +string (with only whitespaces) is not considered as empty. |
| 10 | + |
| 11 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#Coalesce). |
| 12 | + |
| 13 | +**Example**: |
| 14 | +``` |
| 15 | +"tracking_number": { "custom_func": { |
| 16 | + "name": "coalesce", |
| 17 | + "args": [ |
| 18 | + { "xpath": "tracking_number_h002_cn" }, |
| 19 | + { "xpath": "tracking_number_h001" } |
| 20 | + ] |
| 21 | +}} |
| 22 | +``` |
| 23 | +If IDR node `tracking_number_h002_cn` value is `""` and `tracking_number_h001` value is `"ABC"`, |
| 24 | +then the result field `tracking_number` value is `"ABC"`. |
| 25 | +--- |
| 26 | + |
| 27 | +> ### concat |
| 28 | +
|
| 29 | +**Synopsis**: `concat` concatenates a number of strings together. If no strings specified, `""` is |
| 30 | +returned. |
| 31 | + |
| 32 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#Concat). |
| 33 | + |
| 34 | +**Example**: |
| 35 | +``` |
| 36 | +"event_date_time": { "custom_func": { |
| 37 | + "name": "concat", |
| 38 | + "args": [ |
| 39 | + { "xpath": "event_date" }, |
| 40 | + { "const": "T" }, |
| 41 | + { "xpath": "event_time" } |
| 42 | + ] |
| 43 | +}} |
| 44 | +``` |
| 45 | +If IDR node `event_date` value is `"12/31/2020"` and `event_time` value is `"12:34:56"`, |
| 46 | +then the result field `event_date_time` value is `"12/31/2020T12:34:56"`. |
| 47 | +--- |
| 48 | + |
| 49 | +> ### dateTimeLayoutToRFC3339 |
| 50 | +
|
| 51 | +**Synopsis**: `dateTimeLayoutToRFC3339` parses a datetime string according to a given layout, and |
| 52 | +normalizes and returns it in RFC3339 format. |
| 53 | + |
| 54 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#DateTimeLayoutToRFC3339). |
| 55 | + |
| 56 | +**Example**: |
| 57 | +``` |
| 58 | +"day_before_month": { "custom_func": { |
| 59 | + "name": "dateTimeLayoutToRFC3339", |
| 60 | + "args": [ |
| 61 | + { "xpath": "DayBeforeMonth" }, |
| 62 | + { "const": "02/01/06T15:04:05", "_comment": "layout" }, |
| 63 | + { "const": "false", "_comment": "layoutTZ" }, |
| 64 | + { "const": "Pacific/Auckland", "_comment": "fromTZ" }, |
| 65 | + { "const": "America/Los_Angeles", "_comment": "toTZ" } |
| 66 | + ] |
| 67 | +}} |
| 68 | +``` |
| 69 | +If IDR node `DayBeforeMonth` value is `"31/12/20T12:34:56"`, then the result field |
| 70 | +`day_before_month` value is `"2020-12-30T15:34:56-08:00"`: first, input `"31/12/20T12:34:56"` |
| 71 | +is parsed in the time zone of `"Pacific/Auckland"` which is GMT+13 at that moment of time. |
| 72 | +So the input datetime string, if translated into UTC, is `"2020-12-30T23:34:56Z"`. Now the caller |
| 73 | +specifies the desired output timezone to be `"America/Los_Angeles"` which is GMT-8 at that moment |
| 74 | +of time, so the eventual output is `"2020-12-30T15:34:56-08:00"`. |
| 75 | + |
| 76 | +Param `layoutTZ` should be a boolean string value `"true"` or `"false"`, depending on if the |
| 77 | +provided `layout` param contains TZ info (such as `Z` suffix, or tz offset like `-08:00`) in it or |
| 78 | +not. If `layout` has TZ info, then `fromTZ` param will be ignored; if `layout` and input don't have |
| 79 | +TZ info, and `fromTZ` is specified, then the datetime string will be parsed in as if it's in the |
| 80 | +`fromTZ` timezone. If `toTZ` is empty, then whatever the tz from the input parsing will remain intact; |
| 81 | +or the parsed input datetime will be converted into the `toTZ`. |
| 82 | + |
| 83 | +If you're not sure, please check |
| 84 | +[this sample](../extensions/omniv21/samples/xml/1_datetime_parse_and_format.schema.json) to find out |
| 85 | +more subtleties about date time parsing and conversion. |
| 86 | +--- |
| 87 | + |
| 88 | +> ### dateTimeToEpoch |
| 89 | +
|
| 90 | +**Synopsis**: `dateTimeToEpoch` parses a datetime string intelligently, and returns its epoch number. |
| 91 | + |
| 92 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#DateTimeToEpoch). |
| 93 | + |
| 94 | +**Example**: |
| 95 | +``` |
| 96 | +"epoch": { "custom_func": { |
| 97 | + "name": "dateTimeToEpoch", |
| 98 | + "args": [ |
| 99 | + { "xpath": "event_datetime" }, |
| 100 | + { "const": "", "_comment": "fromTZ" }, |
| 101 | + { "const": "SECOND", "_comment": "unit" } |
| 102 | + ] |
| 103 | +}} |
| 104 | +``` |
| 105 | +If IDR node `event_datetime` value is `"12/31/2020T12:34:56Z"`, then the result field |
| 106 | +`epoch` value is `"1609418096"`: first, input `"12/31/2020T12:34:56Z"` |
| 107 | +will be parsed in as is (since it has `Z` suffix, so it is time-zoned, plus `fromTZ` is `""`). |
| 108 | +Then the function converts the input datetime to epoch seconds. |
| 109 | + |
| 110 | +Param `unit` has two valid values: `"SECOND"` or `"MILLISECOND"`. |
| 111 | + |
| 112 | +--- |
| 113 | + |
| 114 | +> ### dateTimeToRFC3339 |
| 115 | +
|
| 116 | +**Synopsis**: `dateTimeToRFC3339` parses a datetime string intelligently, normalizes and returns it |
| 117 | +in RFC3339 format. |
| 118 | + |
| 119 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#DateTimeToRFC3339). |
| 120 | + |
| 121 | +**Example**: |
| 122 | +``` |
| 123 | +"no_tz_date_time_use_to_tz": { "custom_func": { |
| 124 | + "name": "dateTimeToRFC3339", |
| 125 | + "args": [ |
| 126 | + { "xpath": "DateTimeWithNoTZ" }, |
| 127 | + { "const": "", "_comment": "fromTZ" }, |
| 128 | + { "const": "America/Los_Angeles", "_comment": "toTZ" } |
| 129 | + ] |
| 130 | +}}, |
| 131 | +``` |
| 132 | +This `custom_func` params and behavior is very similar to |
| 133 | +[`dateTimeLayoutToRFC3339`](#datetimelayouttorfc3339) except that it doesn't need a `layout` and it |
| 134 | +instead tries to parse the input datetime string intelligently. |
| 135 | + |
| 136 | +If you're not sure, please check |
| 137 | +[this sample](../extensions/omniv21/samples/xml/1_datetime_parse_and_format.schema.json) to find out |
| 138 | +more subtleties about date time parsing and conversion. |
| 139 | +--- |
| 140 | + |
| 141 | +> ### epochToDateTimeRFC3339 |
| 142 | +
|
| 143 | +**Synopsis**: `epochToDateTimeRFC3339` translates an epoch timestamp into an RFC3339 formatted datetime |
| 144 | +string. |
| 145 | + |
| 146 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#EpochToDateTimeRFC3339). |
| 147 | + |
| 148 | +**Example**: |
| 149 | +``` |
| 150 | +"epoch_to_datetime": { "custom_func": { |
| 151 | + "name": "epochToDateTimeRFC3339", |
| 152 | + "args": [ |
| 153 | + { "xpath": "event_epoch" }, |
| 154 | + { "const": "MILLISECOND", "_comment": "unit" } |
| 155 | + ] |
| 156 | +}} |
| 157 | +``` |
| 158 | +If IDR node `event_epoch` value is `"1609418096000"`, then the result field |
| 159 | +`epoch_to_datetime` value is `"2020-12-31T12:34:56Z"`: first, input `"1609418096000"` |
| 160 | +will be parsed in as epoch value in milliseconds. Then the function converts the epoch value |
| 161 | +to RFC3339 string. |
| 162 | + |
| 163 | +Param `unit` has two valid values: `"SECOND"` or `"MILLISECOND"`. |
| 164 | + |
| 165 | +There is an optional param at the end, `tz`: if not specified, the output will be in UTC (`Z`) |
| 166 | +time zone; if specified, it must be of a standard IANA time zone string, such as |
| 167 | +`"America/Los_Angeles"`. |
| 168 | +--- |
| 169 | + |
| 170 | +> ### lower |
| 171 | +
|
| 172 | +**Synopsis**: `lower` lowers the case of an input string. |
| 173 | + |
| 174 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#Lower). |
| 175 | + |
| 176 | +**Example**: |
| 177 | +``` |
| 178 | +"carrier": { "custom_func": { "name": "lower", "args": [ { "xpath": "../GLOBAL/carrier" } ] } }, |
| 179 | +``` |
| 180 | +If IDR node `../GLOBAL/carrier` value is `"ABC"`, then the result field `carrier` value is `"abc"`. |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +> ### now |
| 185 | +
|
| 186 | +**Synopsis**: `now` returns the current time in UTC in RFC3339 format. |
| 187 | + |
| 188 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#Now). |
| 189 | + |
| 190 | +**Example**: |
| 191 | +``` |
| 192 | +"now_datetime": { "custom_func": { "name": "now" }}, |
| 193 | +``` |
| 194 | +The result field `now_datetime` value will be the current system datetime in UTC in RFC3339. |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +> ### upper |
| 199 | +> |
| 200 | +**Synopsis**: `upper` uppers the case of an input string. |
| 201 | + |
| 202 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#Upper). |
| 203 | + |
| 204 | +**Example**: |
| 205 | +``` |
| 206 | +"carrier": { "custom_func": { "name": "upper", "args": [ { "xpath": "../GLOBAL/carrier" } ] } }, |
| 207 | +``` |
| 208 | +If IDR node `../GLOBAL/carrier` value is `"abc"`, then the result field `carrier` value is `"ABC"`. |
| 209 | + |
| 210 | +--- |
| 211 | + |
| 212 | +> ### uuidv3 |
| 213 | +
|
| 214 | +**Synopsis**: `uuidv3` uses MD5 to produce a consistent/stable UUID for an input string. |
| 215 | + |
| 216 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/customfuncs#UUIDv3). |
| 217 | + |
| 218 | +**Example**: |
| 219 | +``` |
| 220 | +"unique_customer_order_id": { "custom_func": { |
| 221 | + "name": "uuidv3", |
| 222 | + "args": [ |
| 223 | + { "custom_func": { |
| 224 | + "name": "concat", |
| 225 | + "args: [ |
| 226 | + { "xpath": "customer_id" }, |
| 227 | + { "const": "/" }, |
| 228 | + { "xpath": "order_id" } |
| 229 | + ] |
| 230 | + }} |
| 231 | + ] |
| 232 | +}} |
| 233 | +``` |
| 234 | +The result field `unique_customer_order_id` will contain the value of an MD5 hash of the concatenated |
| 235 | +string of customer_id value, `"/"`, and order_id value. |
| 236 | + |
| 237 | +--- |
| 238 | + |
| 239 | +## `omni.2.1` Schema Handler Specific `custom_func` |
| 240 | + |
| 241 | +> ### copy |
| 242 | +
|
| 243 | +**Synopsis**: `copy` copies the current contextual `idr.Node` and returns it as a JSON marshaling |
| 244 | +friendly `interface{}`. |
| 245 | + |
| 246 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/extensions/omniv21/customfuncs#CopyFunc). |
| 247 | + |
| 248 | +**Example**: |
| 249 | +``` |
| 250 | +"first_book": { "xpath": "book[position() = 1]", "custom_func": { "name": "copy"} }, |
| 251 | +``` |
| 252 | +The result field `first_book` will be an exact copy of first `book` node from the input. |
| 253 | + |
| 254 | +--- |
| 255 | + |
| 256 | +> ### javascript |
| 257 | +
|
| 258 | +**Synopsis**: `javascript` runs a javascript. |
| 259 | + |
| 260 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/extensions/omniv21/customfuncs#JavaScript). |
| 261 | + |
| 262 | +**Example**: |
| 263 | +``` |
| 264 | +"avg_price": { |
| 265 | + "custom_func": { |
| 266 | + "name": "javascript", |
| 267 | + "args": [ |
| 268 | + { "const": "t=0; for(i=0; i<prices.length; i++) { t+=prices[i]; } Math.floor(t*100/prices.length)/100;" }, |
| 269 | + { "const": "prices" }, { "array": [ { "xpath": "books/*/price", "type": "float" } ] } |
| 270 | + ] |
| 271 | + } |
| 272 | +}, |
| 273 | +``` |
| 274 | +The result field `avg_price` will contain the average price (to the 2nd decimal places) of all the |
| 275 | +book prices. |
| 276 | + |
| 277 | +For more information about `javascript`, check this |
| 278 | +[in-depth explanation](./use_of_custom_funcs.md#javascript-and-javascript_with_context). |
| 279 | +--- |
| 280 | + |
| 281 | +> ### javascript_with_context |
| 282 | +
|
| 283 | +**Synopsis**: `javascript_with_context` runs a javascript with contextual `_node` provided. |
| 284 | + |
| 285 | +**Pkg doc**: [here](https://pkg.go.dev/github.com/jf-tech/omniparser/extensions/omniv21/customfuncs#JavaScriptWithContext). |
| 286 | + |
| 287 | +**Example**: |
| 288 | +``` |
| 289 | +"full_name": { "xpath": "./personal_info", "custom_func" { |
| 290 | + "name": "javascript_with_context", |
| 291 | + "args": [ |
| 292 | + { "const": "var n = JSON.parse(_node); n.['Last Name'] + ', ' + n.['First Name']" } |
| 293 | + ] |
| 294 | +}} |
| 295 | +``` |
| 296 | +The result field `full_name` will be a concatenated string of the last name and the first name from |
| 297 | +the current IDR node. |
| 298 | + |
| 299 | +For more information about `javascript_with_context`, check this |
| 300 | +[in-depth explanation](./use_of_custom_funcs.md#javascript-and-javascript_with_context). |
| 301 | +--- |
0 commit comments