enhancement
major
minor
defect
critical
major
minor
major
#30086
XML-Import: Die Datei „ <update> “ unter <unless-known> muss die Struktur der untergeordneten Elemente, die sie aktualisiert, wiedergeben.
Weiterverfolgung von #29974, beobachtet mit 8.0.0-alpha12 beim ETS-Import von E-Home (haumacher/ehome #38, doc/tl-todo.md).
<unless-known><update condition=…> wendet Handler auf ein bekanntes Element an, und <object-ref> innerhalb seines <dispatch> -Tags greift über dessen ID auf ein untergeordnetes Element zu. Um einem bekannten KNX-Anwendungsprogramm die Texte einer Sprache zur Verfügung zu stellen, die ihm fehlen, müsste der <update> -Abschnitt die gesamte texttragende Struktur des Programms neu definieren: etwa zehn Elementtypen auf mehreren Verschachtelungsebenen (Parametertypen, Parameter, Parameterblöcke, Kommunikationsobjekte, Aufzählungswerte, …), jeweils mit einem <object-ref> und dessen `<set-translation>`s – eine zweite Kopie der Struktur, die die erstellenden Handler bereits beschreiben.
Reproduktion
Ein bekanntes Objekt P1 mit einem untergeordneten Element C1 (beide mit deutschen Texten) und der Eingabe
<Program Id="P1" Name="…"><Static><Children><Child Id="C1" Text="…"/></Children></Static></Program>
auf Englisch: Das Setzen von text@en von C1 erfordert <update><dispatch><tag name="Static"><dispatch><tag name="Children"><dispatch><tag name="Child"><object-ref id-attribute="Id">… – den vollständigen Pfad für jeden Elementtyp, der einen Text enthält.
Gewünscht
Ein Aktualisierungsmodus, der anhand der ID auf jedes untergeordnete Element mit einer ID angewendet wird, die auf ein bekanntes Objekt verweist, wobei die Attribut-Handler verwendet werden, die der erstellende Abschnitt für diesen Elementtyp deklariert (oder eine deklarierte Menge von Attribut-Handlern pro Tag), ohne die Verschachtelung neu anzugeben.
Workaround in E-Home
Der Handler <unless-known-program> (UnlessKnownProgram, TranslationsImport#importBaseTexts), der den Teilbaum des Elements durchläuft und die Texte aller Elemente setzt, deren ID bekannt ist.
Lösung
Die Attribut-Handler eines Elementtyps werden einmalig im Erstellungsabschnitt deklariert und durch eine ID benannt; der Aktualisierungsabschnitt gibt lediglich an, welches Tag welche Handler verwendet:
{{{#!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): Wendet seine Inhalts-Handler auf das aktuelle Element an, sonst nichts (keine Änderung des Geltungsbereichs oder der Variablen). Anhand seiner ID kann auf eine Gruppe von Handlern von anderer Stelle aus mit <ref handler-id="…"/> verwiesen werden.
- <update-known> (UpdateKnown): Durchläuft den gesamten Teilbaum des aktuellen Elements in beliebiger Tiefe und verarbeitet das aktuelle Element. Jeder <tag> -Eintrag benennt ein Tag, wobei das obligatorische id-Attribut die ID dieses Elementtyps enthält (sie unterscheidet sich je nach Elementtyp), eine optionale var sowie die anzuwendenden Handler. Ein Element, dessen Tag aufgeführt ist und dessen ID auf ein bekanntes Objekt verweist (ein zuvor importiertes oder durch ein umschließendes <resolve-existing> gefundenes Objekt), erhält die Handler seines Eintrags, wobei „this“ (und „var“) an dieses Objekt gebunden werden; anschließend wird die Durchquerung in seinen Nachkommen fortgesetzt, sofern die Handler das Element nicht bereits verarbeitet haben. Nicht aufgeführte Tags, Elemente ohne oder mit einer leeren ID sowie unbekannte IDs werden ohne Meldung weitergeleitet; ihre Nachkommen werden weiterhin besucht. Das aktuelle Element selbst wird durch die Handler neben <update-known> aktualisiert. Es wird nichts erstellt und nichts verknüpft.
- Es ist nicht möglich, die Attribut-Handler implizit aus dem erstellenden <object> zu übernehmen: Dessen Inhalt vermischt Attribut-Handler mit dem verschachtelten <dispatch>. <group id> macht die Auswahl explizit.
Dokumentation
Die Syntax von XML-Importdefinitionen wird im Entwicklerkapitel „xml-import“ (Modul com.top_logic.xio, lesbar mit dem tl-mcp-Tool „read_doc“ und im Dokumentationsfenster einer React-Anwendung) beschrieben: Struktur und Dispatch, Objekte und IDs, Werte und Übersetzungen, Verknüpfungen, Variablen und TL-Script sowie das Importieren in vorhandene Daten (<resolve-existing>, <unless-known>/`<update>`, <group>, <update-known>) mit einem Beispiel zum Hinzufügen einer zweiten Sprache.
Test
- test.com.top_logic.xio.importer.TestXmlImporter#testUpdateKnown: Ein zweiter Import in einer anderen Sprache fügt die Texte zum bekannten Element und dessen Nachkommen auf mehreren Ebenen unterhalb von Wrapper-Elementen hinzu, erstellt jedoch kein Objekt; ein unbekannter Nachkomme wird nicht erstellt, während seine bekannten Nachkommen weiterhin aktualisiert werden; ein nicht aufgeführtes Tag, ein falsches ID-Attribut für ein Tag und eine leere ID führen zu keiner Aktualisierung.
- test.com.top_logic.xio.importer.TestXmlImporter#testUpdateKnownMissingIdAttribute: Ein <tag> ohne id-Attribut ist ein Konfigurationsfehler.