Data Entry Template Schema
A data entry template defines structured form content used by clinicians when recording coded data. Completed fields are written to the patient's care record as coded notes, observations, or allergy/intolerance entries.
Note that the XML root element is still named consultationTemplate. This entity was renamed from Consultation Template to Data Entry Template, but the schema itself is unchanged, so templates already published stay valid and need no modification.
The version attribute on the root element is fixed and must be set to 1.0.
An optional <presentingReasonCodes> element (one or more <code> SNOMED CT concept IDs) can precede <form> to associate the template with specific presenting reasons, so it's suggested to the clinician when a matching reason for the encounter is recorded.
Example
<?xml version="1.0" encoding="UTF-8"?>
<consultationTemplate version="1.0" templateName="Diabetes Annual Review">
<form title="Diabetes Annual Review">
<radioButtons name="bpControl" label="Blood pressure control">
<radioOption label="Well controlled (below 140/80)" value="controlled">
<ifChecked>
<careRecordNote code="163020007" heading="163020007"/>
</ifChecked>
</radioOption>
<radioOption label="Poorly controlled" value="uncontrolled">
<ifChecked>
<careRecordNote code="163030003" heading="163030003"/>
</ifChecked>
</radioOption>
</radioButtons>
<quantity name="hba1c" label="HbA1c (mmol/mol)" minValue="0" maxValue="200">
<ifValueSet>
<careRecordObservation code="1019431006" heading="1019431006" unitOfMeasure="767002"/>
</ifValueSet>
</quantity>
<checkboxGroup name="complications" label="Complications">
<checkboxOption label="Retinopathy" value="retinopathy">
<ifChecked>
<careRecordNote code="4855003" heading="4855003"/>
</ifChecked>
</checkboxOption>
<checkboxOption label="Neuropathy" value="neuropathy">
<ifChecked>
<careRecordNote code="230572002" heading="230572002"/>
</ifChecked>
</checkboxOption>
</checkboxGroup>
<quickActions name="reviewActions" label="Review actions" heading="413294000">
<futureAction name="referEye" label="Refer for eye screening"
conceptId="384729004"
dueDateType="DATE"
dueInMonths="3"/>
</quickActions>
</form>
</consultationTemplate>
Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<!-- ===== Simple types ===== -->
<xs:simpleType name="snomedCode">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]+"/>
<xs:minLength value="6"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="nonEmptyString">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<!-- ===== Attribute groups ===== -->
<xs:attributeGroup name="conditionAttributes">
<xs:attribute name="else" type="xs:string"/>
<xs:attribute name="if" type="xs:string"/>
</xs:attributeGroup>
<xs:attributeGroup name="topLevelFormElementAttributes">
<xs:attributeGroup ref="conditionAttributes"/>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:ID">
<xs:pattern value="[A-Za-z][A-Za-z0-9_]+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="label" type="xs:string"/>
</xs:attributeGroup>
<!-- ===== Core container types ===== -->
<xs:complexType name="layoutElementContainerType">
<xs:sequence>
<!-- Permit any of these tags in any order in any number -->
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="section" type="sectionType"/>
<xs:element name="fieldset" type="fieldsetType"/>
<xs:element name="infoBanner" type="infoBannerType"/>
<xs:element name="warningBanner" type="warningBannerType"/>
<xs:element name="systemBanner" type="infoBannerType"/>
<xs:element name="checkbox" type="checkboxType"/>
<xs:element name="checkboxGroup" type="checkboxGroupType">
<!-- identity constraint on local element -->
<xs:key name="checkboxOptionValue">
<xs:selector xpath="./checkboxOption"/>
<xs:field xpath="@value"/>
</xs:key>
</xs:element>
<xs:element name="radioButtons" type="radioButtonsType">
<xs:key name="radioOptionValue">
<xs:selector xpath="./radioOption"/>
<xs:field xpath="@value"/>
</xs:key>
</xs:element>
<xs:element name="select" type="selectType">
<xs:key name="selectOptionValue">
<xs:selector xpath="./selectOption"/>
<xs:field xpath="@value"/>
</xs:key>
</xs:element>
<xs:element name="textInput" type="textInputType"/>
<xs:element name="textarea" type="textareaType"/>
<xs:element name="quantity" type="quantityType"/>
<xs:element name="date" type="dateType"/>
<xs:element name="time" type="timeType"/>
<xs:element name="bloodPressure" type="bloodPressureType"/>
<xs:element name="footer" type="xs:string"/>
<xs:element name="quickActions" type="quickActionsType"/>
<xs:element name="component" type="componentReferenceType"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="topLevelFormElementType">
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
</xs:complexType>
<!-- ===== Root: the ONLY global element... all templates must be in a consultationTemplate tag ===== -->
<xs:element name="consultationTemplate">
<xs:complexType>
<xs:sequence>
<xs:element name="presentingReasonCodes" type="presentingReasonCodesType" minOccurs="0"/>
<xs:element name="form" type="formType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="version" use="required" fixed="1.0"/>
<xs:attribute name="templateName" type="nonEmptyString"/>
</xs:complexType>
</xs:element>
<!-- ===== Form with required title ===== -->
<xs:complexType name="formType">
<xs:complexContent>
<xs:extension base="layoutElementContainerType">
<xs:attribute name="title" use="required" type="nonEmptyString"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- ===== Reference to a data entry template component, replaced by its content when compiled ===== -->
<xs:complexType name="componentReferenceType">
<xs:attribute name="id" use="required" type="nonEmptyString"/>
</xs:complexType>
<!-- ===== Presenting reason codes ===== -->
<xs:complexType name="presentingReasonCodesType">
<xs:sequence>
<xs:element name="code" type="snomedCode" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- ===== Layout element types ===== -->
<xs:complexType name="sectionType">
<xs:complexContent>
<xs:extension base="layoutElementContainerType"/>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="fieldsetType">
<xs:complexContent>
<xs:extension base="layoutElementContainerType">
<xs:attribute name="title" use="required" type="nonEmptyString"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="infoBannerType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attributeGroup ref="conditionAttributes"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="warningBannerType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attributeGroup ref="conditionAttributes"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<!-- ===== Form control types ===== -->
<xs:complexType name="checkboxType">
<xs:all>
<xs:element name="ifChecked" type="ifCheckedType" minOccurs="0"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
<xs:attribute name="text" use="required" type="nonEmptyString"/>
<xs:attribute name="value" use="required" type="nonEmptyString"/>
</xs:complexType>
<xs:complexType name="checkboxGroupType">
<xs:sequence>
<xs:element name="checkboxOption" type="checkboxOptionType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
<xs:attribute name="twoColumns" type="xs:boolean"/>
</xs:complexType>
<xs:complexType name="checkboxOptionType">
<xs:all>
<xs:element name="ifChecked" type="ifCheckedType" minOccurs="0"/>
</xs:all>
<xs:attribute name="label" use="required" type="nonEmptyString"/>
<xs:attribute name="value" use="required" type="nonEmptyString"/>
</xs:complexType>
<xs:complexType name="radioButtonsType">
<xs:sequence>
<xs:element name="radioOption" type="radioOptionType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
</xs:complexType>
<xs:complexType name="radioOptionType">
<xs:all>
<xs:element name="ifChecked" type="ifCheckedType" minOccurs="0"/>
</xs:all>
<xs:attribute name="label" use="required" type="nonEmptyString"/>
<xs:attribute name="value" use="required" type="nonEmptyString"/>
</xs:complexType>
<xs:complexType name="selectType">
<xs:sequence>
<xs:element name="selectOption" type="selectOptionType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
</xs:complexType>
<xs:complexType name="selectOptionType">
<xs:all>
<xs:element name="ifSelected" type="ifSelectedType" minOccurs="0"/>
</xs:all>
<xs:attribute name="label" use="required" type="nonEmptyString"/>
<xs:attribute name="value" use="required" type="nonEmptyString"/>
</xs:complexType>
<xs:complexType name="textInputType">
<xs:all>
<xs:element name="ifTextSet" type="ifTextSetType"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
</xs:complexType>
<xs:complexType name="textareaType">
<xs:all>
<xs:element name="ifTextSet" type="ifTextSetType"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
</xs:complexType>
<xs:complexType name="quantityType">
<xs:all>
<xs:element name="ifValueSet" type="ifValueSetType"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
<xs:attribute name="unit" type="xs:string"/>
<xs:attribute name="minValue" type="xs:float"/>
<xs:attribute name="maxValue" type="xs:float"/>
</xs:complexType>
<xs:complexType name="dateType">
<xs:all>
<xs:element name="ifValueSet" type="ifValueSetType" minOccurs="0"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
<xs:attribute name="maxDate" type="xs:date"/>
<xs:attribute name="minDate" type="xs:date"/>
</xs:complexType>
<xs:complexType name="timeType">
<xs:complexContent>
<xs:extension base="topLevelFormElementType"/>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="bloodPressureType">
<xs:all>
<xs:element name="ifValueSet" type="ifValueSetType"/>
</xs:all>
<xs:attributeGroup ref="topLevelFormElementAttributes"/>
<xs:attribute name="decimalPlaces" type="xs:string"/>
<xs:attribute name="maxValue" type="xs:float"/>
<xs:attribute name="minValue" type="xs:float"/>
</xs:complexType>
<!-- ===== Quick action attribute group ===== -->
<xs:attributeGroup name="actionAttributes">
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:ID">
<xs:pattern value="[A-Za-z][A-Za-z0-9_]+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="label" use="required" type="xs:string"/>
<xs:attribute name="if" type="xs:string"/>
<xs:attribute name="else" type="xs:string"/>
</xs:attributeGroup>
<!-- ===== Quick action types ===== -->
<xs:complexType name="simpleActionType">
<xs:attributeGroup ref="actionAttributes"/>
</xs:complexType>
<xs:complexType name="prescriptionActionType">
<xs:complexContent>
<xs:extension base="simpleActionType">
<xs:attribute name="drugCode" use="required" type="nonEmptyString"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="immunisationActionType">
<xs:complexContent>
<xs:extension base="simpleActionType">
<xs:attribute name="vaccineCode" use="required" type="nonEmptyString"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="futureActionType">
<xs:complexContent>
<xs:extension base="simpleActionType">
<xs:attribute name="conceptId" use="required" type="nonEmptyString"/>
<xs:attribute name="dueDateType">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="UNKNOWN_DATE"/>
<xs:enumeration value="DATE"/>
<xs:enumeration value="MONTH_YEAR"/>
<xs:enumeration value="DATE_RANGE"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="dueInMonths" type="xs:integer"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="communicationActionType">
<xs:complexContent>
<xs:extension base="simpleActionType">
<xs:attribute name="conceptId" use="required" type="nonEmptyString"/>
<xs:attribute name="messageBody" type="xs:string"/>
<xs:attribute name="templateId" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!--
bodySite is optional: omit it to open the procedure form with the body site blank, which
is right for a procedure that has no side or site to record.
-->
<xs:complexType name="procedureActionType">
<xs:complexContent>
<xs:extension base="simpleActionType">
<xs:attribute name="procedureCode" use="required" type="snomedCode"/>
<xs:attribute name="bodySite" type="snomedCode"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="quickActionsType">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="prescription" type="prescriptionActionType"/>
<xs:element name="immunisation" type="immunisationActionType"/>
<xs:element name="procedure" type="procedureActionType"/>
<xs:element name="fitNote" type="simpleActionType"/>
<xs:element name="referral" type="simpleActionType"/>
<xs:element name="investigationRequest" type="simpleActionType"/>
<xs:element name="document" type="simpleActionType"/>
<xs:element name="futureAction" type="futureActionType"/>
<xs:element name="communication" type="communicationActionType"/>
</xs:choice>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:ID">
<xs:pattern value="[A-Za-z][A-Za-z0-9_]+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="label" type="xs:string"/>
<xs:attribute name="heading" type="snomedCode"/>
<xs:attribute name="headingDescription" type="nonEmptyString"/>
</xs:complexType>
<!-- ===== Conditional blocks ===== -->
<xs:complexType name="ifCheckedType">
<xs:all>
<xs:element name="careRecordNote" type="careRecordNoteType" minOccurs="0"/>
<xs:element name="careRecordAllergyIntolerance" type="careRecordAllergyIntoleranceType" minOccurs="0"/>
</xs:all>
</xs:complexType>
<xs:complexType name="ifSelectedType">
<xs:all>
<xs:element name="careRecordNote" type="careRecordNoteType" minOccurs="0"/>
<xs:element name="careRecordAllergyIntolerance" type="careRecordAllergyIntoleranceType" minOccurs="0"/>
</xs:all>
</xs:complexType>
<xs:complexType name="ifTextSetType">
<xs:all>
<xs:element name="careRecordNote" type="careRecordNoteType"/>
</xs:all>
</xs:complexType>
<xs:complexType name="ifValueSetType">
<xs:all>
<xs:element name="careRecordObservation" type="careRecordObservationType"/>
</xs:all>
</xs:complexType>
<!-- ===== Care record elements ===== -->
<xs:complexType name="careRecordNoteType">
<xs:attribute name="code" type="snomedCode"/>
<xs:attribute name="heading" type="snomedCode"/>
<xs:attribute name="headingDescription" type="nonEmptyString"/>
<xs:attribute name="note" type="xs:string"/>
</xs:complexType>
<xs:complexType name="careRecordAllergyIntoleranceType">
<xs:attribute name="code" type="snomedCode"/>
<xs:attribute name="heading" type="snomedCode"/>
<xs:attribute name="headingDescription" type="nonEmptyString"/>
</xs:complexType>
<xs:complexType name="careRecordObservationType">
<xs:attribute name="code" use="required" type="snomedCode"/>
<xs:attribute name="heading" type="snomedCode"/>
<xs:attribute name="headingDescription" type="nonEmptyString"/>
<xs:attribute name="unitOfMeasure" type="snomedCode"/>
<xs:attribute name="additionalInformation" type="xs:string"/>
</xs:complexType>
</xs:schema>
Form controls
| Element | Description | Care record hook |
|---|---|---|
section | Grouping container with no visible title. Supports if/else conditions. | None |
fieldset | Grouping container with a required title. Supports if/else conditions. | None |
infoBanner | Plain-text information banner. Supports if/else conditions. | None |
warningBanner | Warning-style banner. Supports if/else conditions. | None |
systemBanner | System-style banner. Medicus uses it to replace an archived component's content. Supports if/else conditions. | None |
checkbox | Single checkbox. Requires text and value. | ifChecked |
checkboxGroup | Multiple checkboxes. Each checkboxOption has label and value. Optional twoColumns. | ifChecked per option |
radioButtons | Radio button group. Each radioOption has label and value. | ifChecked per option |
select | Dropdown. Each selectOption has label and value. | ifSelected per option |
textInput | Single-line text. | ifTextSet (required) |
textarea | Multi-line text. | ifTextSet (required) |
quantity | Numeric entry. Optional unit, minValue, maxValue. | ifValueSet (required) |
date | Date picker. Optional minDate, maxDate (YYYY-MM-DD). | ifValueSet (optional) |
time | Time picker. | None |
bloodPressure | Blood pressure entry. Optional minValue, maxValue, decimalPlaces. | ifValueSet (required) |
footer | Plain-text footer string. | None |
quickActions | One or more clinical action shortcuts (prescriptions, referrals, future actions, communications). Requires a heading, a headingDescription, or both. | None |
component | Reference to a data entry template component. Requires an id, which is the component's identifier. Replaced by the component's current content when the template is compiled. | From the component's content |
Care record filing
| Attribute | Required on | Description |
|---|---|---|
careRecordNote @code | Optional | SNOMED CT concept ID for the note. |
careRecordNote @heading | One of heading or headingDescription | SNOMED CT concept ID used as the note heading. |
careRecordNote @headingDescription | One of heading or headingDescription | Free-text heading. With heading, it replaces the SNOMED CT term as the heading's text. |
careRecordNote @note | Optional | Additional free-text note. |
careRecordAllergyIntolerance @code | Optional | SNOMED CT concept ID for the allergy/intolerance. |
careRecordAllergyIntolerance @heading | One of heading or headingDescription | SNOMED CT concept ID used as the heading. |
careRecordAllergyIntolerance @headingDescription | One of heading or headingDescription | Free-text heading. With heading, it replaces the SNOMED CT term as the heading's text. |
careRecordObservation @code | Required | SNOMED CT concept ID for the observation. |
careRecordObservation @heading | One of heading or headingDescription | SNOMED CT concept ID used as the heading. |
careRecordObservation @headingDescription | One of heading or headingDescription | Free-text heading. With heading, it replaces the SNOMED CT term as the heading's text. |
careRecordObservation @unitOfMeasure | Optional | SNOMED CT concept ID for the unit. |
careRecordObservation @additionalInformation | Optional | Extra context stored with the observation. |
Default headings
Medicus provides a standard set of SNOMED CT concept IDs to use as the heading value on care record elements and quickActions:
| Concept ID | Description |
|---|---|
717121000000105 | History |
715851000000102 | Examination |
37331000000100 | Impression (proxy code) |
717371000000107 | Plan |
Care record elements and quickActions need a heading, a headingDescription, or both. This differs from patient questionnaire templates, where heading is not part of the schema.
A heading with a SNOMED CT concept ID files under any heading in the consultation with the same concept ID, whatever its text. A free-text heading files under a heading with the same text and no concept ID.