enhancement
major
minor
defect
critical
major
minor
major
#30086
XML import: <update> of <unless-known> must restate the structure of the descendants it updates
Follow-up of #29974, observed with 8.0.0-alpha12 in the ETS import of E-Home (haumacher/ehome #38, doc/tl-todo.md).
<unless-known><update condition=…> applies handlers to a known element, and <object-ref> inside its <dispatch> reaches a descendant by its ID. To give a known KNX application program the texts of a language it lacks, the <update> section would have to restate the program's whole text-carrying structure: about ten element types at several nesting levels (parameter types, parameters, parameter blocks, communication objects, enumeration values, …), each with an <object-ref> and its `<set-translation>`s - a second copy of the structure the creating handlers already describe.
Reproduction
A known object P1 with a child C1 (both with German texts) and the input
<Program Id="P1" Name="…"><Static><Children><Child Id="C1" Text="…"/></Children></Static></Program>
in English: setting text@en of C1 requires <update><dispatch><tag name="Static"><dispatch><tag name="Children"><dispatch><tag name="Child"><object-ref id-attribute="Id">… - the full path, for every element type that carries a text.
Wanted
An update mode that applies by ID to every descendant element with an ID that resolves to a known object, using the attribute handlers the creating section declares for that element type (or a declared set of attribute handlers per tag), without restating the nesting.
Workaround in E-Home
The handler <unless-known-program> (UnlessKnownProgram, TranslationsImport#importBaseTexts), which walks the element's subtree and sets the texts of every element whose ID is known.
Lösung
The attribute handlers of an element type are declared once in the creating section and named by an ID; the update section only says which tag uses which handlers:
{{{#!xml <unless-known id-attribute="Id">
<object model-type="…:Program" id-attribute="Id">
<group id="program-texts">
<set-translation name="name" xml-attribute="Name" language-var="lang"/>
</group>
<dispatch>
… <tag name="Child">
<object model-type="…:Child" id-attribute="Id">
<group id="child-texts">
<set-translation name="text" xml-attribute="Text" language-var="lang"/>
</group>
…
</object>
<update condition="…" arguments="lang">
<ref handler-id="program-texts"/>
<update-known>
<tag name="Child" id-attribute="Id"><ref handler-id="child-texts"/></tag>
<tag name="Parameter" id-attribute="ParamRef"><ref handler-id="parameter-texts"/></tag>
</update-known>
</update>
</unless-known> }}}
- <group> (GroupHandler): applies its content handlers to the current element, nothing else (no change of scope or variables). With its id a set of handlers can be referenced from elsewhere with <ref handler-id="…"/>.
- <update-known> (UpdateKnown): walks the whole subtree of the current element at any depth and consumes the current element. Each <tag> entry names a tag, the mandatory id-attribute holding the ID of that element type (it differs per element type), an optional var, and the handlers to apply. An element whose tag is listed and whose ID resolves to a known object (an object imported before or found by an enclosing <resolve-existing>) gets the handlers of its entry with this (and var) bound to that object; then the walk continues into its children, unless the handlers consumed the element. Unlisted tags, elements without or with an empty ID, and unknown IDs are passed through without message, their descendants are still visited. The current element itself is updated by the handlers next to <update-known>. Nothing is created and nothing is linked.
- Taking the attribute handlers implicitly from the creating <object> is not possible: its content mixes attribute handlers with the nested <dispatch>. <group id> makes the choice explicit.
Documentation
The syntax of XML import definitions is described in the developer chapter xml-import (module com.top_logic.xio, readable with the tl-mcp tool read_doc and in the Documentation window of a React application): structure and dispatch, objects and IDs, values and translations, linking, variables and TL-Script, and importing into existing data (<resolve-existing>, <unless-known>/`<update>`, <group>, <update-known>) with a worked example adding a second language.
Test
- test.com.top_logic.xio.importer.TestXmlImporter#testUpdateKnown: a second import in another language adds the texts to the known item and its descendants at several levels below wrapper elements, creates no object; an unknown descendant is not created while its known descendants are still updated; an unlisted tag, the wrong ID attribute for a tag and an empty ID update nothing.
- test.com.top_logic.xio.importer.TestXmlImporter#testUpdateKnownMissingIdAttribute: a <tag> without id-attribute is a configuration error.