XPath vs ODK round()

[uh oh, here comes trouble, the 'provocateur' is back.. :wink: ] So I'm been playing around with a bunch of Xpath expressions in XForm calculate() bindings, and ran across the issue that the ODK (javaRosa?) re-implements the XPath round() function, namely it adds a second parameter specifying the number of decimal places to round to (see https://opendatakit.github.io/xforms-spec/#xpath-functions). I can certainly see the usefulness of now being able to round to a certain number of decimal places - instead of having to do a round((foo * 100) div 100) to get 2 decimal places - but I think this should have been done using a different function name - say roundN() - rather than clobbering the well-defined and well-established pre-existing XPath one.

Most importantly, this disparity can cause real problems when trying to deploy XForms; specifically, if using KoboToolbox, the following simple XForm - using XPath's round() - works fine under the Kobo's previewer (aka enketo):

<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <h:head>
    <h:title>test round()</h:title>
    <model>
      <instance>
        <data id="snapshot_xml">
          <calculation/>
          <result_calculation/>
          <meta>
            <instanceID/>
          </meta>
        </data>
      </instance>
      <bind calculate="round(1.2345)" nodeset="/data/calculation" required="false()" type="string"/>
      <bind nodeset="/data/result_calculation" readonly="true()" required="false()" type="string"/>
      <bind calculate="concat('uuid:', uuid())" nodeset="/data/meta/instanceID" readonly="true()" type="string"/>
    </model>
  </h:head>
  <h:body>
    <input ref="/data/result_calculation">
      <label>result = <output value=" /data/calculation "/></label></input>
  </h:body>
</h:html>

but if you try to deploy the form with Kobo it will fail (!) with:

unable to deploy: org.javarosa.xpath.XPathUnhandledException[The problem was located in calculate expression for ${calculation} XPath evaluation: cannot handle function 'round' requires 2 arguments. Only 1 provided.]

You could argue the problem is between Kobo using javaRosa to verify the XForm (?) and enketo not using it (?). But really I think the root of the issue is that ODK is introducing an (unecessary?) incompatibility with existing (and supported) XPath 1.0 functions, by using the same XPath function name but now changing the required number of arguments, and as a consequence clobbering the XPath one.

Thoughts?

  • Gareth
2 Likes

Welcome back, @Xiphware!

The issue for adding the single-parameter round is at https://github.com/opendatakit/javarosa/issues/173. If someone is looking for a straightforward way to get started in JavaRosa development, this would be a great one. Otherwise I'll make sure it's in before the next release.

Thanks for highlighting this issue! There's been a lot of work going on to improve standards documentation and compliance recently. Help identifying this kind of discrepancy is much appreciated. :blush:

1 Like

Thank you for the link - it looks like the issue is already on your radar; I'll track it there.

cheers,

  • G
1 Like

This had been sitting for awhile and I was able to implement it very quickly so I went ahead and did it.

1 Like