<?xml version="1.0" encoding="UTF-8"?>
<metanorma xmlns="https://www.metanorma.org/ns/standoc" type="semantic" version="2.9.0" schema-version="v2.2.0" flavor="ribose">
<bibdata type="standard">
<title language="en" type="main">LutaML LML — declarations reference</title>
<docidentifier primary="true" type="Ribose Inc.">RS 3010(wd)</docidentifier><docnumber>RS 3010</docnumber><contributor><role type="author"/><organization>
<name>Ribose Inc.</name>
</organization></contributor><contributor><role type="author"/><person>
<name><completename>Ronald Tse</completename></name>
</person></contributor><contributor><role type="author"><description>committee</description></role><organization>
<name>Ribose Inc.</name>
<subdivision type="Committee" subtype="technical">
<name>LutaML</name>
</subdivision></organization></contributor><contributor><role type="publisher"/><organization>
<name>Ribose Inc.</name>
</organization></contributor><edition>1.0</edition><language>en</language><script>Latn</script><status><stage>working-draft</stage></status><copyright><from>2026</from><owner><organization>
<name>Ribose Inc.</name>
</organization></owner></copyright><ext><doctype>standard</doctype><flavor>ribose</flavor></ext></bibdata><metanorma-extension><semantic-metadata><stage-published>false</stage-published></semantic-metadata>
<presentation-metadata><toc-heading-levels>2</toc-heading-levels><html-toc-heading-levels>2</html-toc-heading-levels><doc-toc-heading-levels>2</doc-toc-heading-levels><pdf-toc-heading-levels>2</pdf-toc-heading-levels></presentation-metadata></metanorma-extension>
<boilerplate><copyright-statement>

<clause id="_81bb91f1-8ca7-1476-7150-6c55a0e1276d" obligation="normative"><p id="_2f99fb1a-6c8b-c002-e8cc-ea45a873756c">© Ribose Inc. 2026</p>
</clause>
</copyright-statement>

<license-statement>

<clause id="_3179d22c-816d-e694-6037-341f744bc6dc" obligation="normative">
<title id="_5ad8fb30-fcae-1072-87a2-407e6b4939ec">Warning for Drafts</title>
<p id="_a24807ee-0381-7ef8-1167-c3aacbb0fd73">This document is not a Ribose Standard. It is distributed for review and comment, and is subject to change without notice and may not be referred to as a Standard. Recipients of this draft are invited to submit, with their comments, notification of any relevant patent rights of which they are aware and to provide supporting documentation.</p>
</clause>
</license-statement>

<legal-statement>

<clause id="_7e0f3c63-3fc9-65cf-37f7-b94afa0dbc5d" obligation="normative"><p id="_50bbfa02-61c3-8332-bad8-61e7389d1808">All rights reserved. Unless otherwise specified, no part of this publication may be reproduced or utilized otherwise in any form or by any means, electronic or mechanical, including photocopying, or posting on the internet or an intranet, without prior written permission. Permission can be requested from the address below.</p>
</clause>
</legal-statement>

<feedback-statement>

<clause id="_f1d37672-deca-a850-dd2a-b66137bed601" obligation="normative"><p id="_e252883d-879c-4220-abfd-4f8ea82738e9" anchor="boilerplate-name" align="left">Ribose Inc.</p>

<p id="_80954cc8-1f49-9d20-5987-829595995a92" anchor="boilerplate-address" align="left">Suite 1, 8/F, New Henry House<br/> 10 Ice House Street<br/> Central<br/> Hong Kong<br/> <br/> <link target="mailto:copyright@ribose.com"/><br/> <link target="https://www.ribose.com">www.ribose.com</link></p>
</clause>
</feedback-statement>
</boilerplate><sections><clause id="_76ed3846-22e8-aea2-df01-05304f426f14" type="scope" obligation="normative">
<title id="_f70b6ff6-6131-0e24-81e1-850dbe94b63d">Scope</title>
<p id="_2cd4de7d-ca21-d081-303b-9ffecd02df7a">This document specifies the <strong>declaration constructs</strong> of the LutaML Model Language (LML) as implemented by  <tt>lutaml-lml</tt> 0.1.8: serialization mapping blocks, instance-type overrides, attribute defaults and nil policy, derived fields, grammar-backed string formats, and enum member payloads including table-driven members. The base models-and-instances syntax is specified in RS 3001 and the accompanying  <tt>lutaml-lml</tt> syntax guide.</p>
</clause>

<clause id="_672fef4d-2702-3822-dfff-b48daba25c7a" obligation="normative">
<title id="_fdce21ab-29d2-eb98-7437-7c28ad5237c1">Serialization mappings</title>
<p id="_5a544422-441a-3ef6-f0b8-e38704235c96">Serialization mappings bind classes to their serialization wire forms. They are declared as  <strong>sibling constructs linked to their class by name</strong> — <tt>mapping &lt;format&gt; &lt;class&gt;</tt> — or inside the class body, where the enclosing class is the implied target.</p>

<p id="_efd823b4-5439-7775-858e-18de25ac80c3"><tt>`</tt>lml models Ceramics {   namespace CeramicsNs {     uri “<link target="http://example.com/ceramics"/>”     prefix “cer”   }</p>

<figure id="_ca91b540-5006-7fdc-111b-5d960d6356d7"><pre id="_31a0d3b8-7b1b-9aef-59c4-55527f80a70e">  class Ceramic {
    attribute location, String
    attribute kiln, String
    attribute notes, String
  }
}</pre></figure>

<p id="_ddd8cf8b-bfff-cdcb-c9b6-17258609e0c1">mapping xml Ceramic {   element “ceramic”   namespace CeramicsNs   map_element “location” location   map_attribute “kiln” kiln   map_content notes }</p>

<p id="_d8cf6f6a-dfee-5a3d-df65-9fd4a75dbb9a">mapping key_value Ceramic {   map “full-name” location   map_key to_instance key_name   map_value as_attribute values } <tt>`</tt></p>

<p id="_bef40244-e098-04c5-43ac-84f0fc855b73">XML mapping rules follow the host implementation’s model: <tt>element</tt> declares the element name,  <tt>namespace &lt;reference&gt;</tt> applies a context namespace,  <tt>map_element</tt>/<tt>map_attribute</tt>/<tt>map_content</tt> bind wire names to model attributes, and  <tt>mixed_content</tt> declares mixed content. The key-value family (<tt>yaml</tt>, <tt>json</tt>, <tt>toml</tt>, <tt>key_value</tt>) uses <tt>map</tt>, <tt>map_key to_instance</tt>, and <tt>map_value to_instance</tt>/<tt>as_attribute</tt>.</p>

<p id="_8aa3c4c4-53ac-1a38-fa54-1bf6b1655208">Namespaces are declared once in the enclosing <tt>models</tt> scope; mappings reference them by name. When the scope declares exactly one namespace it applies implicitly; several namespaces without an explicit reference is a compile-time error. Prefix-less namespaces act as the default namespace (<tt>xmlns</tt>).</p>
</clause>

<clause id="_291e932d-c74d-dfd2-6d2a-558ca3f3b526" obligation="normative">
<title id="_152a83d4-89a6-563d-cd33-1c72fa07351d">Mapping blocks</title>
<p id="_371f41a7-2373-71b1-1fd8-d0820585934f">A <tt>mapping</tt> block declares serialization wire names for a class’s attributes — the serialized key differs from the attribute name.</p>

<sourcecode id="_fd58f3f6-0137-6ea3-d0b3-221382b4eeab" lang="lml"><body>class Widget {
  attribute name { type String cardinality 1 }
  mapping yaml { map "full-name", to: "name" }
}</body></sourcecode>


<table id="_7e50801b-e2fc-9e48-a44d-2a78588c34c4"><colgroup><col width="25%"/><col width="75%"/></colgroup><thead><tr id="_21af0696-6909-73af-6072-c3bcb3935b63"><th id="_896d6ef2-9afe-2a99-46c6-1965e21c5d68" valign="top" align="left">Part</th>
<th id="_b14ddce2-8745-a237-e068-8715a57178cc" valign="top" align="left">Meaning</th>
</tr></thead>
<tbody><tr id="_7e7a4b24-974a-37ba-61be-2ed539e90c5b"><td id="_61a6ae4d-5b03-3abc-4a3a-5784e8d246b1" valign="top" align="left"><tt>yaml</tt></td>
<td id="_596060fe-e23b-e84a-fa4a-9544e2066cc5" valign="top" align="left">target format; one block per format (<tt>yaml</tt>, <tt>xml</tt>, <tt>json</tt>, <tt>toml</tt>, <tt>csv</tt>)</td>
</tr><tr id="_3ddfcd53-c189-aff4-43a0-1a56634d6e6e"><td id="_6463995b-8916-da1e-fd39-907c532c32b1" valign="top" align="left"><tt>map "{wire}", to: "{attribute}"</tt></td>
<td id="_bbe80e91-781e-45d0-95fd-e656a6e36b9b" valign="top" align="left">a wire-name entry; <tt>{wire}</tt> is the serialized key, <tt>{attribute}</tt> the model attribute</td>
</tr></tbody>
</table>

<p id="_629a2135-3f4d-abfd-7732-4d44f1d5b709">The compiler emits the corresponding lutaml-model mapping block. Multiple <tt>mapping</tt> blocks may appear; each format is emitted once.</p>
</clause>

<clause id="_57d47643-b3ac-a918-e5eb-682ad75072b2" obligation="normative">
<title id="_278e24bf-317c-368c-90c1-5da891e7b5ce">Instance-type override (<tt>isa</tt>)</title>
<p id="_e8423ae6-b3d1-4f66-f532-d8812cdbf8f3">The <tt>isa</tt> keyword overrides the type of an instance; a <tt>type</tt> attribute is ordinary data.</p>

<sourcecode id="_62c202c5-be2c-2b7f-8065-2eb41a4dec5b" lang="lml"><body>instance S158Checks {
  isa ValidationChecks
  type = Type::standard
}</body></sourcecode>


<dl id="_4a786152-4004-4e24-82d3-0ebb0fad094b"><dt><tt>{type}</tt></dt>
<dd id="_f11c1e7b-b8c3-59ce-3cbf-1f188a600274"><p id="_7ddd936b-4b00-2ecf-08bf-138439509da7">the overridden (instance-of) type <tt>type = ...</tt>:: an ordinary data attribute — identifier-kind fields named <tt>type</tt> remain usable as data</p>
</dd>
</dl>

<p id="_6544caa2-6880-ecd4-3969-321e3b5784e2">The bare <tt>instance {Type} { ... }</tt> header form is unchanged.</p>
</clause>

<clause id="_23bd22d8-ddf5-25fd-5474-f1af453c43c1" obligation="normative">
<title id="_9a433f3d-cf3e-c1f2-b62b-d0f491392330">Attribute defaults and nil policy</title>
<p id="_5ff814c1-3325-4351-f413-ec304e59e615">Inside an attribute block:</p>

<sourcecode id="_4fe2885d-3a19-6f8d-b766-7b63c44a30c9" lang="lml"><body>attribute originator {
  type String
  cardinality 0..1
  default "iso"
  render_nil false
}</body></sourcecode>


<dl id="_977cd491-43c5-75d9-afce-75f6653f1623"><dt><tt>default "{literal}"</tt></dt>
<dd id="_f1d1a037-3836-1b69-82dc-d27d4c405aa4"><p id="_fed491b7-4f45-1279-d907-09b22753b851">literal-only default; applied only when the input is <strong>absent</strong> — an explicit nil stays explicit. A declared literal wins over the optional-marker nil implied by a  <tt>0..1</tt> cardinality.</p>
</dd>
<dt><tt>render_nil {true|false}</tt></dt>
<dd id="_cdb177ca-16bd-3e14-1809-5757bf13a12b"><p id="_f4721ae8-6451-ff18-c376-4096fd18fd23">nil policy on serialization; the name mirrors the lutaml-model mapping option, and the compiler applies it to the key-value mapping rules.</p>
</dd>
</dl>
</clause>

<clause id="_14dca0dd-62c2-608a-0b84-723b400d842c" obligation="normative">
<title id="_f1843bc6-d729-63d6-54f2-7d32b2291df7">Derived fields</title>
<sourcecode id="_b3d7b10e-b0bd-905f-da95-17f0fe5e1e58" lang="lml"><body>derive urn: String</body></sourcecode>


<p id="_b79ad93e-b247-7499-5f7a-7115fa0b0383">Declares the field’s existence and type; the field participates in mappings like any attribute. The  <strong>computation</strong> is bound by the binder from the grammar artifact’s derive specifications — LML never defines computation.</p>
</clause>

<clause id="_9e5b0708-0ea3-d752-56bb-f3c088bc9df1" obligation="normative">
<title id="_3780e0d3-7369-9de2-6414-06a373ef6876">Grammar-backed string formats</title>
<sourcecode id="_129357fd-da5b-01a5-c4f5-e5794acdd5cf" lang="lml"><body>class IsoIdentifier {
  string_format :pubid_iso {
    artifact "pubid/iso"
    root "iso_identifier"
  }
}</body></sourcecode>


<p id="_13182f55-a896-6d4a-0778-e06453757a04">Declares that instances of the class serialize to and from an identifier string parsed by a grammar artifact. The declaration is a thin reference: the artifact (a compiled grammar with typed bindings) is the single source of truth for capture maps and render specifications — LML never duplicates them.</p>

<table id="_a8647808-aef7-6471-6bbe-7955270b6b54"><colgroup><col width="25%"/><col width="75%"/></colgroup><thead><tr id="_db5fe052-18a1-67ae-f820-f408ecba4c65"><th id="_be00645d-2f76-41d1-7e3f-80f6a9157bb0" valign="top" align="left">Part</th>
<th id="_b18c8cf6-9933-a1fa-ceee-6167cc8538f0" valign="top" align="left">Meaning</th>
</tr></thead>
<tbody><tr id="_dd8cd03a-0362-4243-74d7-68b5bf7e9823"><td id="_3ce59dd1-478d-d9d3-8b43-87dbd9089589" valign="top" align="left"><tt>:pubid_iso</tt></td>
<td id="_01a8b54f-0533-d2ee-696e-829b90b826fc" valign="top" align="left">the registered format name (per flavor — flavors differ in grammar, not just data)</td>
</tr><tr id="_b3a0e296-ed44-90ba-9d1d-34d4099dd7e8"><td id="_e5d613da-3e93-15a9-cecb-1638eb830e23" valign="top" align="left"><tt>artifact "{ref}"</tt></td>
<td id="_7c29373b-e95c-91c1-a7bb-4f679580326b" valign="top" align="left">artifact reference, resolved through the compiler’s <tt>artifact_paths</tt> map or <tt>default_artifact</tt></td>
</tr><tr id="_8662365b-503d-5dbc-9808-0d62e6dedbe8"><td id="_6158e589-d5dd-d521-3fb9-c9e78128269b" valign="top" align="left"><tt>root "{entry}"</tt></td>
<td id="_6edaec0d-0c7f-3dc0-1c27-4698bf2fd36d" valign="top" align="left">the grammar entry rule</td>
</tr></tbody>
</table>

<p id="_7e8b4029-bdbc-2559-6221-55bec54d8c9e">Registration defines <tt>from_{format}</tt> on the compiled model, and the format is registered in the single lutaml-model  <tt>FormatRegistry</tt>. A <tt>models</tt>-block <tt>string_format</tt> acts as the default for classes without their own.</p>
</clause>

<clause id="_726029db-82e0-08ed-2b7d-71f2e7169cc8" obligation="normative">
<title id="_36e9e2ec-0fbb-aded-be41-591068a43050">Enum member payloads</title>
<sourcecode id="_8fa181e5-8df5-e64c-46ed-b0725a17d1e7" lang="lml"><body>enum Stage {
  member_fields { abbreviation String  urn_segment String }

  draft10   { abbreviation = "WD"  urn_segment = "wd" }
  published { abbreviation = "IS"  urn_segment = "published" }
}</body></sourcecode>


<dl id="_33cc8590-d1ad-d91b-cf31-56da8dd305f6"><dt><tt>member_fields { ... }</tt></dt>
<dd id="_6b8e5b25-9f98-7403-ad50-8bfc75264014"><p id="_add2721d-f2db-a269-6adc-fbfe9503e425">the typed payload schema shared by all members <tt>{member} { {field} = {value} ... }</tt>:: inline payload lines, validated against the schema at compile time — an undeclared field is an error, a missing optional field is nil</p>
</dd>
</dl>
</clause>

<clause id="_03ae3ade-48e8-6abe-00ac-8c75f2137a1c" obligation="normative">
<title id="_861d180d-a709-4f64-aa76-ec5825f51aae">Table-driven enums</title>
<sourcecode id="_67653b70-fbc8-d98c-8e92-d8628a7f1f0e" lang="lml"><body>enum Stage {
  member_fields { abbreviation String  urn_segment String }
  from_table "stages" {
    artifact "pubid/iso"
  }
}</body></sourcecode>


<p id="_8544c8c3-4ecb-755b-7c9b-47151ede4b9a">Members are expanded at compile time from a table in a grammar artifact’s <tt>tables</tt> section — the same data source that preprocessing lookups and render conditions read. Rows are validated against  <tt>member_fields</tt>: an unknown field is an error; a missing optional field is nil; the member name comes from the row’s  <tt>name</tt> column. Expansion is compile-time, so materialization is deterministic and no data dependency reaches consumer runtimes.</p>

<dl id="_b1b26e37-9c46-3668-b5ad-d310ee0f11d2"><dt><tt>from_table "{name}"</tt></dt>
<dd id="_cf1a778d-aab4-b664-23cf-0d173d64b3ad"><p id="_94b2b3f2-fbd1-4406-5b83-5c1c1597b9fa">the table name within the artifact <tt>artifact "{ref}"</tt>:: the artifact reference; resolved through the compiler’s <tt>artifact_paths</tt> map or <tt>default_artifact</tt></p>
</dd>
</dl>
</clause>

<clause id="_aaeb2c3e-038f-bcde-8013-8484139ba627" obligation="normative">
<title id="_1e3ffc74-16d7-f96c-3131-743a2bef0dd0">Operations</title>
<p id="_4f68c2a7-4861-e0af-d273-f0a34e568b91">A class may carry operations (methods) as structural metadata: a name, an optional symbol visibility, an optional parameter list, an optional return type with cardinality, and property modifiers. Operations carry no executable semantics; they exist so that UML models round-trip through LML without losing their behavioral surface (Enterprise Architect and XMI carry methods on every class).</p>

<p id="_d18670d4-3b3c-257c-fff2-c2de52418775">Syntax:</p>

<sourcecode id="_eaba9b52-7923-bafd-9882-39887c4c9f49" lang="lml"><body>class {name} {
  {visibility} {operation-name}({*parameter}): {return-type}[{cardinality}] {*property}
}</body></sourcecode>


<p id="_e3550916-dcd3-cb88-f843-9ff2a52328b6">Where,</p>

<dl id="_a0e63e8a-0e5c-d82f-d5f6-568e5ab46822"><dt><tt>{visibility}</tt></dt>
<dd id="_983ab0b7-28f1-6fc2-d2dd-4cd74c6904e3"><p id="_b37662f8-cb4e-7fb5-d138-2684952f0890">optional; one of <tt>+</tt> (public), <tt>-</tt> (private), <tt>#</tt> (protected), <tt>~</tt> (package); default <tt>+</tt></p>
</dd>
<dt><tt>{operation-name}</tt></dt>
<dd id="_d406ed80-8e1b-3a1b-9ff5-735c211e5981"><p id="_fa4d7cd3-7710-bf87-a237-4ae559fe93a4">the name of the operation <tt>{*parameter}</tt>:: zero or more parameters, comma-separated <tt>{return-type}</tt>:: optional; the declared return type <tt>{cardinality}</tt>:: optional; the cardinality of the returned collection <tt>{*property}</tt>:: optional; comma-separated property modifiers (for example <tt>ordered</tt>, <tt>unique</tt>, <tt>query</tt>)</p>
</dd>
</dl>

<p id="_47d0107a-b778-9ae7-d644-05d3d7712241">A parameter is:</p>

<sourcecode id="_af01f5d1-ee2b-23c7-88e9-88dd7df65407" lang="lml"><body>[{direction} ]{parameter-name}[: {parameter-type}][ = {default}]</body></sourcecode>


<p id="_5a8074c8-b2ed-b3f8-517d-f16cac4fc552">Where,</p>

<dl id="_ef94dca2-a8d8-3059-e5fd-948d80dcf004"><dt><tt>{direction}</tt></dt>
<dd id="_0cfba223-fb49-37b7-5bd7-e448abe17fb7"><p id="_3c7dccec-4f4a-c1a4-1be6-049b258f482d">optional; one of <tt>in</tt>, <tt>out</tt>, <tt>inout</tt>; default <tt>in</tt></p>
</dd>
<dt><tt>{parameter-name}</tt></dt>
<dd id="_bbc3f81d-7f6a-dd51-0dfb-b38cd88cb67c"><p id="_f997adfc-0a9b-d695-3c63-4b810ec6ec44">the name of the parameter <tt>{parameter-type}</tt>:: optional; the declared parameter type <tt>{default}</tt>:: optional; the parameter’s default value</p>
</dd>
</dl>

<example id="_6c14fcfa-2bb2-77a7-41b3-d967b5d77198"><sourcecode id="_5f4c6950-d06a-35e2-5879-4a5f20e677f6" lang="lml"><body>class Ceramic {
  + getGlazeType(glazeCode: CharacterString = "123"): GlazeType[1..*] {ordered, unique, query}
  - simpleOp(): String
  multi(a: String, b: Integer = 5, in c: Boolean)
}</body></sourcecode> </example>
</clause>
</sections>
</metanorma>
