@@ -11,8 +11,9 @@ produced.
1111
1212# New Job Request Fields
1313
14- Below is an example of a job that uses media selectors. The job uses a two-stage pipeline.
15- The first stage performs language identification. The second performs translation.
14+ Below is an example of a job that uses ` JSON_PATH ` media selectors. The job uses a two-stage
15+ pipeline. The first stage performs language identification. The second performs translation.
16+
1617``` json
1718{
1819 "algorithmProperties" : {},
@@ -43,6 +44,7 @@ The first stage performs language identification. The second performs translatio
4344 "priority" : 4
4445}
4546```
47+
4648- ` $.media.*.mediaSelectorsOutputAction ` : Name of the action that produces content for the media
4749 selectors output file. In the above example, we specify that we want the translated content
4850 from Argos in the media selectors output file rather than the detected language from the first
@@ -68,18 +70,20 @@ The first stage performs language identification. The second performs translatio
6870 of the document will be replaced with the action output. When provided, the selected parts of
6971 the document will contain the original content, followed by the value of this property, and
7072 finally the action output.
73+
7174- ` MEDIA_SELECTORS_DUPLICATE_POLICY ` : Specifies how to handle the case where a job uses media
7275 selectors and there are multiple outputs for a single selection. When set to ` LONGEST ` , the
7376 longer of the two outputs is chosen and the shorter one is discarded. When set to ` ERROR ` ,
7477 duplicates are considered an error. When set to ` JOIN ` , the duplicates are combined using
7578 ` | ` as a delimiter.
79+
7680- ` MEDIA_SELECTORS_NO_MATCHES_IS_ERROR ` : When true and a job uses media selectors, an error will be
7781 generated when none of the selectors match content from the media.
7882
7983
8084# Media Selector Types
8185
82- ` JSON_PATH ` is only type currently supported, but others are planned .
86+ [ ` JSON_PATH ` ] ( #json_path ) and [ ` CSV_COLS ` ] ( #csv_cols ) are currently supported.
8387
8488
8589## JSON_PATH
@@ -94,6 +98,7 @@ other JSON types are ignored. When the JsonPath expression matches an array, eac
9498recursively explored. When the expression matches an object, keys are left unchanged and each value
9599of the object is recursively explored.
96100
101+
97102### JSON_PATH Matching Example
98103
99104``` json
@@ -122,14 +127,14 @@ Expression | Matches
122127` $.key2.key3.*.*[0] ` | d, f
123128
124129
125-
126- # Media Selectors Output File
130+ ### JSON_PATH Output File
127131
128132When media selectors are used, the JsonOutputObject will contain a URI referencing the file
129133location in the ` $.media.*.mediaSelectorsOutputUri ` field.
130134
131- The job from the [ New Job Request Fields section] ( #new-job-request-fields ) could be used with the
132- document below.
135+ For example, consider that the ` mediaUri ` from the job in the
136+ [ New Job Request Fields section] ( #new-job-request-fields ) refers to the document below.
137+
133138``` json
134139{
135140 "otherStuffKey" : [" other stuff value" ],
@@ -166,6 +171,7 @@ document below.
166171```
167172
168173The ` mediaSelectorsOutputUri ` field will refer to a document containing the content below.
174+
169175``` json
170176{
171177 "otherStuffKey" : [" other stuff value" ],
@@ -238,3 +244,213 @@ below.
238244 ]
239245}
240246```
247+
248+
249+ ## CSV_COLS
250+
251+ Used to extract content from specific columns of a CSV file. The expression itself must be a
252+ single row of CSV listing the columns to extract. The ` CSV_SELECTORS_ARE_INDICES ` job property
253+ controls whether the entries refer to column names or zero-based integer indices.
254+
255+
256+ ### CSV-Specific Job Properties
257+
258+ - ` CSV_SELECTORS_ARE_INDICES ` : When ` FALSE ` (the default), the selector expression must contain
259+ column names. When ` TRUE ` the selector should contain the zero-based integer indices of the
260+ columns that should be processed.
261+
262+ - ` CSV_CSV_FIRST_ROW_IS_DATA ` : When ` FALSE ` (the default), the first row is considered headers and
263+ will not be processed. When ` TRUE ` , the first row is considered data and the first row will be
264+ processed.
265+
266+ An issue when processing CSV is that sometimes the first row is considered headers (a.k.a. column
267+ names) and in others the first row is actually data and there are no headers.
268+
269+ - In the default configuration (` CSV_SELECTORS_ARE_INDICES ` = ` FALSE ` and
270+ ` CSV_FIRST_ROW_IS_DATA ` = ` FALSE ` ), the selector expression refers to column names and the
271+ first row is not processed as data.
272+
273+ - If the first row is actual data, and you want to specify the columns by index instead of by
274+ name in the selector expression, set ` CSV_SELECTORS_ARE_INDICES ` = ` TRUE ` and
275+ ` CSV_FIRST_ROW_IS_DATA ` = ` TRUE ` .
276+
277+ - If the first row is headers, and you want to specify the columns by index instead of by
278+ name in the selector expression, set ` CSV_SELECTORS_ARE_INDICES ` = ` TRUE ` and
279+ ` CSV_FIRST_ROW_IS_DATA ` = ` FALSE ` .
280+
281+
282+ ### CSV_COLS Matching Example
283+
284+ The table below shows combinations of values for ` CSV_SELECTORS_ARE_INDICES ` and
285+ ` CSV_FIRST_ROW_IS_DATA ` when matched against this CSV content:
286+
287+ ``` text
288+ header0,header1,"header,2"
289+ a,b,c
290+ d,e,f,g
291+ ```
292+
293+ Expression | ` CSV_SELECTORS_ ` <br >` ARE_INDICES ` | ` CSV_FIRST_ROW_ ` <br >` IS_DATA ` | Matches
294+ ---------------------|---------------|-------------------|------------
295+ ` header0,"header,2" ` | FALSE | FALSE | a, c, d, f
296+ ` header0,"header,2" ` | FALSE | TRUE | header0, "header,2", a, c, d, f
297+ ` header0,headerX ` | FALSE | TRUE / FALSE | ** Error** : "headerX" does not exist
298+ ` header0,header,2 ` | FALSE | TRUE / FALSE | ** Error** : "header" and "2" do not exist
299+ ` header0,"header,2" ` | TRUE | TRUE / FALSE | ** Error** : The expression contains non-integers.
300+ ` 0,2 ` | TRUE | FALSE | a, c, d, f
301+ ` 0,2 ` | TRUE | TRUE | header0, "header,2", a, c, d, f
302+ ` 0,3,4 ` | TRUE | FALSE | a, d, g
303+ ` 0,2 ` | FALSE | TRUE / FALSE | ** Error** : There are no columns with "0" or "2" as the header.
304+
305+
306+ ### CSV Text Encodings
307+
308+ We recommend submitting UTF-8-encoded CSV files, but we do attempt to recognize other text
309+ encodings. When attempting to determine the input file encoding, the Workflow Manager will inspect
310+ the first 12,000 bytes of the file. If all of the 12,000 bytes are valid UTF-8 bytes, then the
311+ Workflow Manager will treat the file as UTF-8. Otherwise, the Workflow Manager will use
312+ [ Tika's ` CharsetDetector ` ] ( https://tika.apache.org/2.9.1/api/org/apache/tika/parser/txt/CharsetDetector.html )
313+ to determine the encoding.
314+
315+ The media selectors output file will always be UTF-8-encoded. If the input file was UTF-8-encoded
316+ and had a byte-order mark, then a byte-order mark will be added to the output file.
317+
318+
319+ #### Byte-order mark
320+
321+ The UTF-8, UTF-16, and UTF-32 text encodings may have a byte-order mark present. The byte-order
322+ mark is the Unicode character named "ZERO WIDTH NO-BREAK SPACE" with a code point of U+FEFF. Each
323+ encoding will encode it as different bytes. For example, in UTF-8 it is encoded with three bytes:
324+ ` 0xEF ` , ` 0xBB ` , ` 0xBF ` .
325+
326+ Many CSV parsers do not have special handling for the byte-order mark. They just treat it as a
327+ normal character and consider it to be the first character in the first cell. The Workflow Manager
328+ discards the byte-order mark before parsing the CSV.
329+
330+
331+ #### Excel
332+
333+ - If you open a CSV file in Microsoft Excel and the text is garbled, you should open the file
334+ in a text editor that supports UTF-8 and see if the text is garbled there too.
335+
336+ - When saving a CSV file from Excel, if you select "CSV (Comma delimited)(* .csv)", Excel will
337+ silently replace East Asian characters with question marks. Selecting
338+ "CSV UTF-8 (Comma delimited) (.csv)" preserves the East Asian characters, but it adds a
339+ byte-order mark to the file.
340+
341+ - If you open a UTF-8-encoded file in Excel, it will treat it as ISO-8859-1 unless the file has
342+ a UTF-8 byte-order mark.
343+
344+ Using a byte-order mark with UTF-8 is uncommon because the UTF-8 encoding does not have endianess
345+ like UTF-16 and UTF-32. The byte-order mark added by Excel can cause problems because a
346+ lot of software does not expect it to be present.
347+
348+
349+ As an example, consider an Excel spreadsheet with the following content:
350+
351+ Col,1 | Col,2
352+ ------|--------
353+ item1 | item2
354+
355+
356+ If you save that as "CSV UTF-8 (Comma delimited) (.csv)" and then ` cat ` the file you will get:
357+
358+ ``` text
359+ "Col,1","Col,2"
360+ item1,item2
361+ ```
362+
363+ Since the two column names contain commas, the cells need to be escaped with quotation marks so that
364+ the internal comma is not interpreted as a record separator. If you parse that file with
365+ [ Python's built-in CSV parser] ( https://docs.python.org/3/library/csv.html ) you get the following
366+ result:
367+
368+ "Col | 1" | Col,2
369+ -------|-------|------
370+ item1 | item2 |
371+
372+
373+ While the first cell above appears to be four characters in length, it is actually five. The first
374+ character is U+FEFF (ZERO WIDTH NO-BREAK SPACE). Since the first cell starts with
375+ U+FEFF (ZERO WIDTH NO-BREAK SPACE), rather than U+0022 (QUOTATION MARK), the first comma is
376+ unescaped so it is interpreted as the record separator.
377+
378+ Since the byte-order mark is invisible when rendered, simply printing the content will not reveal
379+ the issue. It is visible in a hexdump produced with ` hexdump -C ` on Linux or ` Format-Hex ` in
380+ Windows Powershell. In the output from ` hexdump -C ` below, you can see that there is content before
381+ the quotation mark and that content matches the UTF-8-encoded byte-order mark of ` 0xEF ` , ` 0xBB ` ,
382+ ` 0xBF ` .
383+
384+ ``` text
385+ 00000000 ef bb bf 22 43 6f 6c 2c 31 22 2c 22 43 6f 6c 2c |..."Col,1","Col,|
386+ 00000010 32 22 0d 0a 69 74 65 6d 31 2c 69 74 65 6d 32 0d |2"..item1,item2.|
387+ 00000020 0a |.|
388+ ```
389+
390+
391+ ### CSV_COLS Output File
392+
393+ When media selectors are used, a copy of the input file with the specified sections replaced by
394+ component output is produced. The URI to the file will be present in the
395+ ` $.media.*.mediaSelectorsOutputUri ` field.
396+
397+ Below is an example of a job that uses ` CSV_COLS ` media selectors. The job uses a two-stage
398+ pipeline. The first stage performs language identification. The second performs translation.
399+
400+ ``` json
401+ {
402+ "algorithmProperties" : {},
403+ "buildOutput" : true ,
404+ "jobProperties" : {},
405+ "media" : [
406+ {
407+ "mediaUri" : " file:///opt/mpf/share/remote-media/test-csv-translation.csv" ,
408+ "properties" : {},
409+ "mediaSelectorsOutputAction" : " ARGOS TRANSLATION (WITH FF REGION AND NO TASK MERGING) ACTION" ,
410+ "mediaSelectors" : [
411+ {
412+ "type" : " CSV_COLS" ,
413+ "expression" : " Spanish" ,
414+ "resultDetectionProperty" : " TRANSLATION" ,
415+ "selectionProperties" : {}
416+ },
417+ {
418+ "type" : " CSV_COLS" ,
419+ "expression" : " Chinese" ,
420+ "resultDetectionProperty" : " TRANSLATION" ,
421+ "selectionProperties" : {}
422+ }
423+ ]
424+ }
425+ ],
426+ "pipelineName" : " ARGOS TRANSLATION (WITH FASTTEXT LANGUAGE ID) TEXT FILE PIPELINE" ,
427+ "priority" : 4
428+ }
429+ ```
430+
431+ The input file, ` test-csv-translation.csv ` , contains the content below.
432+ ``` text
433+ English,Spanish,Chinese
434+ "Hello, how are you?","¿Hola, cómo estás?",你好吗?
435+ Where is the library?,¿Dónde está la biblioteca?,图书馆在哪里?
436+ What time is it?,¿Qué hora es?,现在是几奌?
437+ ```
438+
439+ The ` mediaSelectorsOutputUri ` field from the output object will refer to a document containing the
440+ content below.
441+ ``` text
442+ English,Spanish,Chinese
443+ "Hello, how are you?","Hello, how are you?",How are you?
444+ Where is the library?,Where's the library?,Where's the library?
445+ What time is it?,What time is it?,What time is it?
446+ ```
447+
448+ If ` MEDIA_SELECTORS_DELIMETER ` was set to " | Translation: ", the file would contain the content
449+ below.
450+
451+ ``` text
452+ English,Spanish,Chinese
453+ "Hello, how are you?","¿Hola, cómo estás? | Translation: Hello, how are you?",你好吗? | Translation: How are you?
454+ Where is the library?,¿Dónde está la biblioteca? | Translation: Where's the library?,图书馆在哪里? | Translation: Where's the library?
455+ What time is it?,¿Qué hora es? | Translation: What time is it?,现在是几奌? | Translation: What time is it?
456+ ```
0 commit comments