Dynamic data attachments in XLSForm

Last updated: 6 May 2026

Dynamic linking allows you to use data from a parent project within child projects, simplifying the management of longitudinal data collection. This article explains how to dynamically link data between KoboToolbox projects.

Note: Dynamic data attachments function similarly to the pulldata() function but eliminate the need for separate CSV files, since the data from a linked parent project serves as the data source.

You can retrieve various non-media responses from a parent project and perform calculations on this linked data in a child project. This can be useful for retrieving baseline data, contact information, or health records in cohort studies, or for confirming or verifying previously collected data.

We recommend using XLSForm to set up dynamic data attachments. For examples of parent and child projects, download sample files here and here. To learn how to set up dynamic data attachments in the KoboToolbox Formbuilder, see Dynamic data attachments using the Formbuilder.

Dynamically linking projects in XLSForm

Dynamically linking projects requires a parent project and at least one child project. The parent project requires no modification from a normal XLSForm. However, setting up the child project(s) involves the following steps:

  1. In the survey worksheet of your XLSForm, add a row and set the question type to xml-external.

  2. In the name column, provide a short name for the parent form. This name can consist of Latin alphabet characters, underscores, and numbers.

survey worksheet

type

name

label

xml-external

parent

survey

  1. Throughout the form, you can retrieve values from the parent project by creating a new question and including the appropriate expression in the calculation column (see table below). You can use the following question types to retrieve data:

    • Use a calculate question type to retrieve and store values for future use within the form or dataset (e.g., for calculations or dynamic question labels).

    • Use text, integer, decimal, date, select_one, or select_multiple question types to include retrieved values as default responses in editable fields. Data edited in the child project will not change the original data in the parent project.

survey worksheet

type

name

label

calculation

xml-external

parent

text

participant_id

What is the participant’s ID?

integer

age

Confirm the participant’s age

instance(‘parent’)/root/data[enrollment_id = current()/../participant_id]/age

survey

Note: To display linked data without allowing users to edit the field, use a calculate question followed by a note question that displays the calculated value. Alternatively, use text, integer, decimal, select_one, or select_multiple questions with the read_only column set to TRUE.

Calculation syntax for dynamic data attachments

In the calculation column of the row where linked data will be retrieved, include one of the expressions in the table below. These expressions are called XPaths.

For each expression in the table below:

  • parent is the unique name assigned to the parent form (e.g., in the xml-external question of the child form).

  • parent_question refers to the name of a question from the parent form.

  • child_question refers to the name of a question from the child form.

  • parent_index_question is the identifying question from the parent form that links it to the child form (e.g., unique ID, organization name).

  • child_index_question is the identifying question from the child form that links it to the parent form (e.g., unique ID, organization name).

  • parent_group refers to the name of the group in the parent form in which the parent_question is located.

  • parent_index_group refers to the name of the group in the parent form in which the parent_index_question is located.

XPath

Description

count(instance('parent')/root/data)

Returns the total number of rows in the parent project.

count(instance('parent')/root/ data[parent_group/parent_question])

Returns the total number of rows in the parent project where parent_question (in parent_group) is not empty.

count(instance('parent')/root/ data[parent_group/parent_question= current()/../child_question])

Returns the total count of instances where the value of parent_question (in parent_group) in the parent project is equal to the value of child_question in the child project.

instance('parent')/root/ data[parent_index_group/parent_index_question= current()/../child_index_question]/parent_group/ parent_question

Returns the value of parent_question (in parent_group) from the parent project where child_index_question in the child project is equal to parent_index_question in the parent project.

instance('parent')/root/ data[parent_index_group/parent_index_question= current()/../child_index_question][position()= 1]/parent_group/parent_question

Same as above, but specifies that only data from the first instance of parent_index_question should be returned, using the [position() = 1] argument. Used in case of possible duplicates in the parent form.

sum(instance('parent')/root/ data/parent_group/parent_question)

Returns the sum of values from parent_question (in parent_group) from the parent project. Note that parent_question must be numeric

max(instance('parent')/root/ data/parent_group/parent_question)

Returns the maximum value entered in parent_question (in parent_group) from the parent project. Note that parent_question must be numeric.

min(instance('parent')/root/ data/parent_group/parent_question)

Returns the minimum value entered in parent_question (in parent_group) from the parent project. Note that parent_question must be numeric.

Note: If the parent question is not included in any group, omit parent_group from the expression

Setting up projects for dynamic linking

Once your XLSForms are set up, log into your KoboToolbox account and follow these steps:

  1. Create and deploy the parent project, if not already deployed.

  2. Enable data sharing for the parent project:

    • In the SETTINGS > Connect Projects tab of the parent project, toggle the Data sharing switch (disabled by default) and click ACKNOWLEDGE AND CONTINUE in the confirmation window.

    • All data is shared by default, but you can restrict specific variables to share with child projects by clicking “Select specific questions to share”.

Note: If projects have different owners, the parent project owner must share the project with the child project owner. The minimum permissions required for dynamic data attachments to work are View form and View submissions. Note that this allows child project administrators to view all parent project data.

  1. Create and deploy the child project.

  2. Connect the child project to the parent project:

    • In the SETTINGS > Connect Projects tab of the child project, click the “Select a different project to import data from.” A dropdown menu will allow you to select a parent project to link.

    • Rename the linked parent project to the xml-external question name defined in the XLSForm and click IMPORT.

    • You can then select specific questions from the parent project to share with the child project (recommended), or select all questions.

  3. If you add new fields to the parent form and wish to use them in the child project, re-import the parent project in the child project settings.

Note: Forms can only be linked together if they are on the same KoboToolbox server.

Dynamically linking a form to itself

It is possible for a parent and child project to be the same project. The steps are the same as those described above. Examples of use cases include:

  • Daily monitoring: If a form is used to survey the same person over time, you can link it to itself to count previous submissions. This can allow you to display a message (e.g., “monitoring is complete”) after a certain number of entries or to inform the enumerator of the number of forms submitted, as shown in the example below.

survey worksheet

type

name

label

calculation

xml-external

monitoring

text

participant_id

What is the participant’s ID?

calculate

count

count(instance(‘monitoring’)/root/ data[monitoring/participant_id = current()/../participant_id])

note

monitoring_note

This participant has been surveyed ${count} times.

survey

  • Registration form: By linking a registration form to itself, you can check whether a user has already been registered. This can allow you to generate an error message or add a constraint if they are already registered, preventing duplicate registrations, as shown in the example below.

survey worksheet

type

name

label

calculation

relevant

xml-external

registration

text

customer_id

What is the customer’s ID number?

calculate

count

count(instance(‘registration’)/root/ data[registration/customer_id = current()/../customer_id])

note

already_registered

This customer is already registered. Please close this form.

${count} > 0

survey

Collecting and managing data with dynamic linking

Data for dynamically linked projects can be collected using the KoboCollect Android app or web forms.

When collecting data, note the following:

  • The parent project must have at least one submission for the child project to function correctly.

  • When collecting data online, there is a five-minute delay in syncing new parent project data with the child project.

  • In offline mode, frequently download the child project to ensure data synchronization with the parent project.

Note: You can configure the KoboCollect Android app to automatically update the parent project's data when an internet connection is available. Go to Settings > Form management > Blank form update mode and select either Previously downloaded forms only or Exactly match server. You can set the automatic download frequency to occur every 15 minutes, every hour, every six hours, or every 24 hours. Note that enabling this setting may increase battery consumption.

Troubleshooting

Error or crash when linking forms If the user interface crashes when you attempt to link forms, check the following:
  • Your XLSForm does not include duplicate question or group names in the name column of the survey worksheet.
  • Your parent project has at least one submission.
If the user interface is still crashing, select only the questions you need to connect the forms, instead of clicking Select all.

Parent data not showing in the child form Check that the calculation syntax in the child form is correct and that the relevant questions are shared in both projects. If your parent question is in a question group, be sure to include the group name in the XPath expression. Note that new parent project data takes up to five minutes to sync when you are online. If you add new fields to the parent form and want to use them in the child project, open the child project settings, re-import the parent project, and redeploy.

Child form loads slowly Large dynamic data attachments can slow down forms, especially when opening a web form for a new submission or when editing existing submissions.

If you are working with a large dataset, share only the questions the child form needs instead of the full list of questions. You can also consider splitting the parent form into multiple forms, for example by district or region, or using a different approach if the dataset is too large for dynamic data attachments.

Dynamic data not refreshing in KoboCollect If you are using KoboCollect and collecting data offline, data must first be submitted to the parent project and then downloaded to your data collection device for the dynamic data attachment to work. Both steps require an internet connection. Downloading parent data is similar to downloading a new version of a form, and the KoboCollect app can be configured to automatically download new data at a set frequency. It is not recommended to rely on dynamic data attachments for data collected offline within a short period of time.

Dynamic data attachment not working inside question groups To pull dynamic data from a parent form into a child form with question groups, ensure the index question (e.g., the identification number) in the child form is in the same group as the calculation for the dynamic data. See sample files Round 1 (Within Groups).xlsx and Round 2 (Within Groups).xlsx for an example of dynamic data attachments within groups.

Dynamic data attachments not pulling values from repeat groups Dynamic data attachments do not currently support pulling values directly from repeat groups in a parent form. If you try to retrieve a value from a repeat group, the child form may return blank values, retrieve only the last repeat entry, or otherwise fail to retrieve the expected data.

As a workaround, you can add one or more calculate questions outside the repeat group in the parent form and use them to store the repeat group values needed in the child form. Then, pull these calculated values into the child form instead of pulling directly from the repeat group.

For more complex workflows, you may need to restructure the parent form, split repeat entries into separate submissions, or process the parent data outside KoboToolbox and attach it as an external CSV.

Parent index variable inside a repeat group Dynamic data attachments do not currently support linking submissions from repeat groups. If the index variable in the parent form is inside a repeat group, the child form will not be able to match and retrieve the expected data.

To avoid this issue, place the linking variable outside the repeat group whenever possible. If each repeated item needs to be linked to a child form, consider restructuring the workflow so that each item is submitted as its own parent submission, rather than as one entry in a repeat group.

For example, instead of collecting all household members in a repeat group within one household submission, you could create a separate parent form where each household member is submitted as an individual submission with a unique ID. The child form can then use that ID to retrieve the correct submission.

Error evaluating fields in KoboCollect If your parent form contains duplicate submissions, you may receive an error message in KoboCollect stating “Error evaluating field / XPath evaluation: type mismatch /This field is repeated.” To solve this issue and pull data only from the first submission containing a specific index value, use the [position()=1] argument, as below:

instance('parent')/root/data[parent_index_group/parent_index_question = current()/../child_index_question][position()=1]/parent_group/parent_question

Cannot update values retrieved from dynamic data attachments If you are pulling dynamic data into integer, text, or select questions and want these fields to remain editable, add a trigger column to your XLSForm. In the row that contains the dynamic data expression, enter the name of the child index question in the trigger column.

This allows the value to be edited manually. The value will update from the parent data only when the response to the index question changes.

Choice names appear instead of choice labels When pulling data from a select_one or select_multiple question, dynamic data attachments will use the choice name, not the choice label. To display the choice label in your child form instead, use one of the following approaches:
  • Pull the data into a select question and include the corresponding labels in the choices tab.
  • In the parent form, use a jr:choice-name() calculation to retrieve the choice label, then pull that calculated value into the child form.