Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common.Import/XML.md

183 lines
15 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- Common/DTS.Common.Import/XML/XMLPre20ParseGroupTemplates.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomDirections.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomTestObjects.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomPositions.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc3s.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc2s.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc1s.cs
- Common/DTS.Common.Import/XML/XMLParseSensorModels.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFilterClasses.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomChannels.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomMainLocations.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomPhysicalDimensions.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseSensors.cs
- Common/DTS.Common.Import/XML/XMLParseUsers.cs
- Common/DTS.Common.Import/XML/XMLParseBase.cs
- Common/DTS.Common.Import/XML/XMLParseTestEngineerDetails.cs
- Common/DTS.Common.Import/XML/XMLParseLabDetails.cs
- Common/DTS.Common.Import/XML/XMLParseGlobalSettings.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseDASList.cs
- Common/DTS.Common.Import/XML/XMLParseCustomerDetails.cs
- Common/DTS.Common.Import/XML/XMLParseSensors.cs
- Common/DTS.Common.Import/XML/XMLParseDASList.cs
- Common/DTS.Common.Import/XML/XMLParseGroupTemplates.cs
- Common/DTS.Common.Import/XML/XMLParseCalibrations.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseCalibrations.cs
- Common/DTS.Common.Import/XML/XMLParseGroups.cs
- Common/DTS.Common.Import/XML/XMLParseTestSetups.cs
generated_at: "2026-04-16T02:07:16.226597+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "87dec39982bd8179"
---
# XML Import Parsers Module Documentation
## 1. Purpose
This module provides a family of XML parsing classes responsible for deserializing versioned XML export files into the systems in-memory `ImportObject` representation during data import operations. Each concrete parser targets a specific data domain (e.g., sensors, groups, channels, test setups, calibration data, MME custom objects) and handles both direct parsing and migration logic for pre-2.0 XML formats. These parsers implement the `IParseVariant` interface, inherit from `XMLParseBase`, and coordinate with other parsers (e.g., via constructor injection) to resolve cross-references and normalize identifiers across related entities. The module serves as the core deserialization layer for backward-compatible XML imports, ensuring robust handling of schema evolution and data integrity constraints.
## 2. Public Interface
All classes inherit from `XMLParseBase` and implement the abstract method `Parse(ref ImportObject importObject)`. Below are the public classes and their key behaviors.
### `XMLParseBase`
- **Constructor**: `XMLParseBase(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- Stores the XML root node, imported file version, cancellation token, and normalization flag.
- Initializes internal XML writer and mapping dictionaries (`_dasIdMapping`, `_groupIdMapping`, `_sensorIdMapping`, `_channelIdMapping`) for cross-entity ID normalization.
- **Protected Methods**:
- `XmlElement GetXmlElement()` Finalizes XML writing and returns the constructed `XmlElement`.
- `bool IsCancelled()` Invokes the cancellation token (defaults to `() => false`).
### `XMLParseSensors`
- **Constructor**: `XMLParseSensors(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `XmlElement ConvertSensors(IEnumerable<SensorData> sensors)` Normalizes sensor `DatabaseId`s (assigns negative IDs starting at -2), updates `_sensorIdMapping`, and writes normalized XML.
- `IEnumerable<SensorData> ParseSensors(XmlElement root)` Parses `SensorData` objects from XML nodes; skips non-`XmlElement` nodes.
### `XMLPre20ParseSensors`
- **Constructor**: `XMLPre20ParseSensors(XmlElement root, double importedVersion, XMLParseSensors xmlParseSensors, Func<bool> isCancelled = null)`
- **Public Methods**:
- `XmlElement MigrateSensors(IEnumerable<SensorData> sensors)` Migrates pre-2.0 sensor data by assigning negative `DatabaseId`s (starting at -1) and writing to XML.
- **Behavior**: Parses sensors, migrates them to the new schema, then delegates to `_xmlParseSensors.ParseSensors()` for final parsing.
### `XMLParseDASList`
- **Constructor**: `XMLParseDASList(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `List<DASHardware> ParseDASList(XmlElement root)` Parses `DASHardware` objects; filters out entries with invalid `DASType` (logs serial numbers to `invalidDAS` list, but does not report errors).
- `XmlElement ConvertDASList(List<DASHardware> dasList)` Normalizes `DASId`s (starting at -2) and updates `_dasIdMapping`.
- **Behavior**: On import, validates `DASType` enum values; skips invalid entries silently.
### `XMLPre20ParseDASList`
- **Constructor**: `XMLPre20ParseDASList(XmlElement root, double importedVersion, XMLParseDASList xmlParseDASList, Func<bool> isCancelled = null)`
- **Public Methods**:
- `List<DASHardware> ParsePre20DASList(XmlElement root)` Parses pre-2.0 `DASHardware` objects.
- `XmlElement MigratePre20DASList(List<DASHardware> dasList)` Assigns negative `DASId`s (starting at -1) and writes to XML.
- **Behavior**: Migrates pre-2.0 DAS list, then delegates to `_xmlParseDASList.ParseDASList()`.
### `XMLParseGroups`
- **Constructor**: `XMLParseGroups(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public Methods**:
- `List<IGroup> ParseGroups(XmlElement root, ref ImportObject importObject)` Parses groups, resolving channel references to imported sensors/DAS via lookup dictionaries. Handles both pre-2.0 (name-based) and post-2.0 (ID-based) group IDs in `_groupIdMapping`.
- `XmlElement ConvertGroups(List<IGroup> staticGroups)` Normalizes group `Id`s (starting at -2), DAS/sensor IDs in channels (using `_dasIdMapping`/`_sensorIdMapping`), and writes to XML. Silently sets `SensorId = 0` for deleted sensors (FB 14308).
- **Behavior**: Normalizes group and channel IDs; handles sensor deletion gracefully.
### `XMLParseGroupTemplates`
- **Constructor**: `XMLParseGroupTemplates(XmlElement root, double importedVersion, ISO.ISO13499FileDb iSO13499FileDb, Func<bool> isCancelled = null)`
- **Public Methods**:
- `IEnumerable<DataPROWin7.DataModel.TestObjectTemplate> ParseGroupTemplates(ref ImportObject importObject, XmlElement root)` Parses group templates, resolving channels from `importObject.CustomChannels()`. Enforces that referenced ISO test objects exist in `importObject.TestObjects()` (throws `NotSupportedException` if missing, FB 8790).
- **Behavior**: Requires pre-parsed custom channels and test objects; validates test object existence.
### `XMLParseTestSetups`
- **Constructor**: `XMLParseTestSetups(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `XmlElement ConvertTestTemplates(IEnumerable<TestTemplate> testTemplates, ImportObject importObject)` Normalizes group IDs, channel IDs (using `_groupIdMapping`, `_channelIdMapping`), and DAS/sensor IDs in channels. Handles missing static group IDs (sets to `null`) and deleted sensors (sets `SensorId = 0`, FB 14308).
- `IEnumerable<TestTemplate> ParseTestTemplate(ImportObject importObject, XmlElement root)` Parses test setups using lookup dictionaries for test objects, groups, customer/lab details, sensors, etc. Catches and logs parsing errors as warnings (FB 36879).
- **Behavior**: Requires pre-parsed entities (groups, sensors, etc.) to resolve references; handles missing/invalid references gracefully.
### `XMLParseCalibrations`
- **Constructor**: `XMLParseCalibrations(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public Methods**:
- `XmlElement ConvertCalibrations(IEnumerable<SensorCalibration> calibrations)` Writes normalized calibration XML.
- `IEnumerable<SensorCalibration> ParseCalibrations(XmlElement root)` Parses calibrations with version-specific logic:
- For `importedVersion >= DataPROPre20XmlVersion`: Direct parsing.
- For `importedVersion == 1.0`: Sets `AtCapacity = false` and infers `SensitivityUnits` (mV/EU, mV/V/EU, or NONE) based on calibration type.
### `XMLPre20ParseCalibrations`
- **Constructor**: `XMLPre20ParseCalibrations(XmlElement root, double importedVersion, XMLParseCalibrations xmlParseCalibrations, Func<bool> isCancelled = null)`
- **Behavior**: Parses pre-2.0 calibrations, adds them to sensors via `AddToSensor()`, then delegates normalization and re-parsing to `_xmlParseCalibrations`.
### `XMLParseMMECustom*` Parsers (e.g., `XMLParseMMECustomChannels`, `XMLParseMMECustomPositions`, etc.)
- **Common Pattern**:
- **Constructor**: `XMLParseMMECustom* (XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public/Protected Methods**:
- `ParseCustom* (XmlElement root)` Parses a list of MME objects (e.g., `ISO.MMEPossibleChannels`, `ISO.MMEPositions`) from XML child nodes.
- `Parse(ref ImportObject importObject)` Adds parsed list to `importObject` via `AddCustom*()` methods.
- **Behavior**: Iterates child `XmlElement`s, calls `ReadXML()` on each, and respects cancellation. No normalization or migration logic (assumes current-version format).
### `XMLPre20ParseGroupTemplates`
- **Constructor**: `XMLPre20ParseGroupTemplates(XmlElement root, double importedVersion, XMLParseGroupTemplates xmlParseGroupTemplates, Func<bool> isCancelled = null)`
- **Behavior**: Delegates parsing to `_xmlParseGroupTemplates.ParseGroupTemplates()`; no migration logic visible.
### `XMLParseUsers`
- **Constructor**: `XMLParseUsers(XmlElement root, double importedVersion, IEnumerable<IUIItems> uiItems, Func<bool> isCancelled = null)`
- **Behavior**: Parses `User` objects using `User.ReadXML()`, passing `uiItems` for UI context.
### `XMLParseTestEngineerDetails`, `XMLParseLabDetails`, `XMLParseCustomerDetails`
- **Pattern**: Parse → Convert → Re-parse → Add to `importObject`.
- `Parse*()` Initial parse.
- `Convert*()` Writes parsed objects to XML.
- Re-parse normalized XML to ensure consistency.
- **Behavior**: All use `Convert*()` to normalize and re-parse; no ID mapping beyond XML structure.
### `XMLParseGlobalSettings`
- **Constructor**: `XMLParseGlobalSettings(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Behavior**: Parses `<SettingName>` and `<SettingValue>` child elements into a `Dictionary<string, string>`.
## 3. Invariants
- **ID Normalization**: All parsers that normalize IDs (e.g., `XMLParseSensors`, `XMLParseDASList`, `XMLParseGroups`, `XMLParseTestSetups`) assign negative integer IDs starting at -1 or -2 (to avoid conflicts with database IDs). Mappings are stored in static dictionaries (`_sensorIdMapping`, `_dasIdMapping`, `_groupIdMapping`, `_channelIdMapping`) and used during cross-entity resolution.
- **Cancellation Handling**: All parsers check `IsCancelled()` before processing each node and return partial results if cancelled.
- **XML Node Validation**: All parsers skip non-`XmlElement` nodes (e.g., whitespace, comments) during iteration.
- **Version-Specific Parsing**: Calibrations and sensors have distinct parsing logic for `importedVersion == 1.0` vs. newer versions.
- **Group Template Validation**: `XMLParseGroupTemplates` enforces that referenced ISO test objects exist in `importObject.TestObjects()`; throws `NotSupportedException` if missing.
- **DAS Type Validation**: `XMLParseDASList` filters out `DASHardware` with invalid `DASType` enums but does not report errors (silently drops entries).
- **Sensor Deletion Handling**: Group and Test Setup parsers set `SensorId = 0` for deleted sensors (FB 14308) to avoid import failures.
## 4. Dependencies
### Internal Dependencies
- **Imports**:
- `DTS.Common.Import.Interfaces` (`ImportObject`, `IParseVariant`, `IImportNotification`, `ImportStatus`, `ImportError`, `ImportSeverityError`)
- `DTS.Common.Interface.*` (e.g., `GroupTemplate`, `Groups.GroupList`, `Sensors`, `Channels`)
- `DTS.SensorDB` (`SensorModel`, `SensorData`, `SensorCalibration`)
- `DataPROWin7.DataModel` (`DASHardware`, `TestObjectTemplate`)
- `ISO.*` (e.g., `MMEPossibleChannels`, `MMETestObjects`, `MMEPositions`, `TestEngineerDetails`, `CustomerDetails`, `LabratoryDetails`)
- `System.Xml` (`XmlElement`, `XmlDocument`, `XmlWriter`)
- **Shared State**:
- Static dictionaries in `XMLParseBase` (`_dasIdMapping`, `_groupIdMapping`, `_sensorIdMapping`, `_channelIdMapping`) are shared across parsers in the same import session.
- `ImportNotification` property used for status updates (settable via property).
- **Constructor Injection**:
- Pre-2.0 parsers (`XMLPre20ParseSensors`, `XMLPre20ParseDASList`, `XMLPre20ParseCalibrations`, `XMLPre20ParseGroupTemplates`) depend on their post-2.0 counterparts to perform normalization and final parsing.
### External Dependencies
- `DataPROWin7.DataModel.DASHardware.ReadXML()` Static method for pre-2.0 DAS parsing.
- `ISO.*.ReadXML()` Static methods for MME object parsing (e.g., `ISO.MMEPossibleChannels.ReadXML()`).
- `User.ReadXML()` Static method for user parsing.
- `SensorData.ReadXML()`, `SensorCalibration.ReadXML()` Static methods for sensor/calibration parsing.
- `DataPROWin7.DataModel.TestObjectTemplate.ReadXML()` Static method for group template parsing.
## 5. Gotchas
- **Silent DAS Filtering**: `XMLParseDASList.ParseDASList()` silently drops DAS entries with invalid `DASType` enums (no error logged or reported).
- **ID Mapping Side Effects**: Static ID mappings in `XMLParseBase` are shared across parsers; clearing them (e.g., in `XMLParseDASList` constructor) may affect other parsers if not coordinated.
- **Version-Specific Calibration Logic**: For `importedVersion == 1.0`, `XMLParseCalibrations` mutates calibration records (e.g., sets `AtCapacity = false`, infers `SensitivityUnits`). This logic is duplicated in `XMLPre20ParseCalibrations`.
- **FB References**: Several parsers reference internal bug IDs (e.g., FB 8790, FB 14308, FB 36879) in comments or exceptions; these are internal tracking references.
- **Test Setup Reference Resolution**: `XMLParseTestSetups.ParseTestTemplate()` uses lookup dictionaries built from `importObject` entities; if entities are not parsed in the correct order, lookups may fail (e.g., missing groups/sensors).
- **Group Template Test Object Validation**: `XMLParseGroupTemplates` throws `NotSupportedException` if a referenced ISO test object is missing; this is a hard failure.
- **XML Writer State**: `XMLParseBase` uses a shared `XmlWriter` instance per parser; reusing the same writer across multiple `Convert*()` calls without reinitialization may cause issues (though current code creates a new `_doc` per instance).
- **Pre-2.0 Migration Assumptions**: `XMLPre20Parse*` parsers assume the target parser (`_xmlParse*`) handles normalization; no validation that the target parser is compatible with the migrated XML structure.
- **Group ID Mapping Ambiguity**: `XMLParseGroups` uses `_groupIdMapping` with keys as `g.Id.ToString()` (post-2.0) or `g.Name` (pre-2.0); this dual-key approach may cause issues if group names collide with numeric IDs.
- **Channel ID Normalization**: `XMLParseTestSetups` normalizes channel IDs *after* normalizing group IDs; order of normalization matters for cross-references.