String-before() and string-after() function support

What is the problem? Please be detailed.
Need a function support string-before() and string-after(). I am fetching an ID from a CSV file which is in the format 000000-Name. I need to extract the numbers before '-'. please help

What ODK tool and version are you using? And on what device and operating system version?
Latest ODK on an android device

What steps can we take to reproduce the problem?

What you have you tried to fix the problem?
Using substring for now but doesn't solve the problem if length of ID changes.

Anything else we should know or have? If you have a test form or screenshots or logs, attach here.

Hi @Zuhaib_Shaik,

Perhaps you could append zeros before the numeric part of your IDs to give it a fixed length in your csv. After that you can use the usual substr(${ID}, 0, 12) assuming your numeric string has 12 digits.

1 Like

Thanks for your reply sir, but the ID's are dynamically generated, can't predict the definite length of it as it is passed on by client. I have just got the format for it.

How do you receive the dynamically generated IDs and how and when do you put them in the CSV file?
Can't you create before saving the CSV file, on top of the id column, a column that contains only the number and load it from there in ODK Collect?
Since the numeric part is separated by a hyphen from the name (text) part, there are functions in Excel that allow to extract the numeric part before the hyphen (or any other separator).

1 Like

Hope this helps,

  1. find string length(str = "000000-Name" - > strlen = 11
    2)find the location of '-'('-' is at str[6])
    3)substring until '-'(substring(str,0,6-1)

Hi @Zuhaib_Shaik,

@Snehaniranjana has given the right approach, but unfortunately there is no function that I'm aware of which can "find location of" the '-' character. (Available functions are listed here)

It is however possible to use if() and regex() to get the desired functionality, as long as there is an upper limit to the number of digits before the '-' character, e.g. ID num will never be longer than 8 digits.

if( regex(${ID},'^\d-'), substr(${ID},0,1),
    if( regex(${ID},'^\d{2}-'), substr(str,0,2),
        if( regex(${ID},'^\d{3}-'), substr(str,0,3),
            if( regex(${ID},'^\d{4}-'), substr(str,0,4),
                'ID could not be extracted'))))

If ID string is a digit followed by '-', return just first character,
else if ID string is 2 digits followed by '-', return first 2 characters,
else if ID string is 3 digits followed by '-', return first 3 characters,
else if ID string is 4 digits followed by '-', return first 4 characters,
else return 'ID could not be extracted'

If your ID is not just digits (0..9), but letters as well (a-z, A-Z) you can use \w instead of \d

If your ID can be more than 4 digits, extend the code above to cater for more digits.

Note: I've tested the regex, but not the rest of the code above


1 Like

Hi Andrew,

I just saw a function named 'position', Will that function help you find
the location of '-'?

Since I am totally new and there is no much description on the function,
let me know if this helps?


Hi @Snehaniranjana,

The position() function is typically used for finding the index/counter of a repeat group (see here), but won't help for what we're wanting to achieve here.


Just to be precise, what you want is for ODK/javaRosa to support the XPath1.0 functions substring-before() and substring-after() [see here].

Note, Enketo appears to fully support XPath1.0, so these will in fact work if you deploy your XForm to Enketo (!) Unfortuantely, javaRosa does not, which means you will be prevented from deploying the same form to ODK Aggregate/KoboToolbox/etc, which perform javaRosa-compat verification when you try submit a new form, and will throw an error when it detects unsupported XPath functions in your calculations:

ODK Validate Errors: org.javarosa.core.log.WrappedException: Error evaluating field 'calculation_001': The problem was located in calculate expression for ${calculation_001} XPath evaluation: cannot handle function 'substring-before' ....

If you can somehow live with just Enketo webforms you could probably limp along... but it means living without ODK Collect (at least until these XPath 1.0 functions are added to javaRosa). Or implementing a long if-then-elseif-... , as described above by Andrew.

Disclaimer: I'm not affiliated with Enketo, just an admirer :slight_smile:

  • Gareth

Hi @Andrew the solution you gave worked for me as the generated ID was 8 to 10 digits followed by a '-' thank you so much for the help.

1 Like

Hi Andrew,what if i want to extract values after the "-"

You want to use the substring-after operator. See the docs:

Absolutely correct. Both substring-before() and substring-after() have since been added into ODK's javaRosa support [by yours truly as it happens].