Skip to content

Reject XLSForm expressions ending with non-ambiguous dangling operators #860

Description

@ukanga

Software and hardware versions

pyxform v4.5.0, Python 3.11

Problem description

pyxform accepts expressions that end with an operator that requires a
right-hand operand when external validation is disabled. For example:

type name relevant
text source_value
integer dependent_question ${source_value} =

Running conversion with validate=False or xls2xform --skip_validate
successfully generates an XForm containing:

<bind
    nodeset="/data/dependent_question"
    relevant="/data/source_value ="
    type="int"
/>

The expression is incomplete because the operator has no right-hand value or
expression. The same problem applies to dangling arithmetic, boolean, and union
operators.

This postpones the error until ODK_Validate.jar flags the generated XForm as
invalid, without identifying the original XLSForm cell.

Steps to reproduce the problem

  1. Create an XLSForm containing the survey rows shown above.

  2. Run:

    xls2xform form.xlsx form.xml --skip_validate

    Alternatively, call convert(..., validate=False).

  3. Observe that conversion succeeds and the incomplete expression is emitted
    into the generated XForm.

Expected behavior

pyxform should raise a PyXFormError before XForm generation, regardless of
whether external validation is enabled.

The error should identify the original sheet, workbook row, and column, for
example:

[row : 3] On the 'survey' sheet, the 'relevant' value is invalid.
An operator must be followed by a value or expression.

Other information

The targeted validation should:

  • Detect comparison operators (=, !=, <, >, <=, >=), arithmetic
    operators (+, -, div, mod), boolean operators (and, or), and the
    union operator (|), including trailing whitespace.
  • Allow terminal * because it can be a valid XPath wildcard, as in /data/*.
  • Allow operator words used as XPath node names, as in /data/and.
  • Check expression-bearing survey, settings, and entities columns.
  • Ignore disabled survey rows.
  • Allow quoted operator characters and static text defaults.
  • Preserve original sheet and header names in error messages.
  • Run when validate=False and with --skip_validate.

pyxform's existing expression lexer can identify the final token, with context
used to distinguish operator words from XPath node names.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions