--- name: jmri-panel-xml description: Edits JMRI Layout Editor panel and tables XML safely by script. Covers what a panel or tables file holds, the names and connections that must agree across it, what JMRI rewrites on Store, why edits must happen with JMRI closed, and how geometry attributes behave. Use when a task reads, generates, or changes a JMRI panel or tables .xml file, when adding or renaming tracks, anchors, end bumpers, turnouts, blocks or masts outside the JMRI GUI, when moving or scaling panel geometry by script, or when a panel loads with missing connections, lost blocks, or vanished edits. Not for signal logic semantics; use jmri-sml-nx for facing blocks, Signal Mast Logic discovery, and Entry/Exit. --- # Editing JMRI panel and tables XML ## The safe sequence 1. Close JMRI. 2. Copy the file somewhere safe. 3. Parse and edit with a real XML library. Do not patch text with regex. 4. Check your edits against the key rules below. 5. Run JMRI's Validate XML File tool. 6. Open the file in JMRI and read the log for errors. 7. Run the Layout Editor Check menu: Un-Connected Tracks, Un-Blocked Tracks, Non-Contiguous Blocks. 8. Store from JMRI once, then diff against your edit to see what JMRI normalised. ## What is in the file The root is `layout-config`. The sections you will touch most: - `turnouts`, `sensors`, `memories`, `blocks`: named beans. - `signalmasts`: the masts themselves. - `layoutblocks`: Layout Blocks, plus the `blockrouting` and `routingStablisedSensor` attributes. - `signalmastlogics`: stored Signal Mast Logic. - `entryexitpairs`: stored NX pairs. - `LayoutEditor`: one element per panel, named by its `name` attribute. Inside `LayoutEditor`: - Icons and labels, such as `signalmasticon` and `sensoricon`. - `layoutturnout`, `layoutSlip`, `levelxing`, `layoutturntable`, `layouttraverser`. - `tracksegment`. - `positionablepoint`: anchors, end bumpers, and edge connectors, by `type`. - `layoutShape`. Not stored at all, so never add them: - Block connectivity. JMRI rebuilds it from the track objects after load. - Block routing tables. - Automatic SML blocks and turnouts. ## Every element needs a class - Give every direct child of `LayoutEditor` a `class` attribute. Copy it from a sibling of the same kind. - Do not modernise class values. JMRI deliberately stores old names such as `...configurexml.TrackSegmentXml` and maps them on load. Why: the panel loader reads `class` on each child, with no null check, to pick the adapter. ## Track names must match their type JMRI finds a connected object by the prefix of its name. Use these prefixes for new `ident` values: | Object | Prefix | Example | |---|---|---| | Turnout | `TO` | `TO12` | | Anchor | `A` | `A40` | | End bumper | `EB` | `EB3` | | Edge connector | `EC` | `EC1` | | Level crossing | `X` | `X2` | | Slip | `SL` | `SL1` | | Turntable | `TUR` | `TUR1` | | Traverser | `TRV` | `TRV1` | | Track segment | `T` | `T77` | - Keep each `ident` unique in the panel. - Do not start a track segment name with `TO`, `TUR` or `TRV`. Those prefixes are tested first, so the lookup goes to the wrong object type and returns nothing. - A prefix outside this table generally logs "unknown type name prefix" and leaves the connection empty. ## Connections must agree at both ends A `tracksegment` names both ends: ```xml