CGMES/CIMXML Gaps¶
1. Non-Standard RDF/XML Serialization (CIMXML)¶
Root Cause Analysis¶
IEEE published CIMXML in 2003, but W3C RDF/XML 1.0 was finalized in 2004 → CIMXML was based on a draft specification.
- Technical Issues:
rdf:IDandrdf:aboutuse non-standard URI formats (e.g., _123 instead of proper URIs)rdf:parseType="Statements"was introduced but is not valid W3C RDF/XML syntax- Multiple graphs in one file violates standard RDF/XML structure
Standard RDF libraries (Apache Jena, rdflib, etc.) cannot parse CIMXML correctly without custom modifications.
How We Solved It¶
In DifferenceModelReader.cs:
// MANUAL HANDLING OF rdf:parseType="Statements"
private string WrapInRdfDocument(string xmlContent, IGraph parentGraph)
{
// Reconstruct proper RDF/XML with correct namespaces
return $"<?xml version=\"1.0\" encoding=\"utf-8\"?><rdf:RDF {namespaces}>{xmlContent}</rdf:RDF>";
}
In CimNodeResolver.cs implementations:
// FIX FOR NON-STANDARD URIs
public string GetInstanceId(INode node)
{
var rawId = GetRawValue(node);
// Convert CIMXML's "_123" to proper "urn:uuid:123"
// Create a normalized URI format for consistent processing
return normalizeId
}
2. Missing Datatype Information¶
Root Cause Analysis¶
CIMXML serialization does not include rdf:datatype attributes for literal values.
- Example:
<cim:GeneratingUnit.maxOperatingP>100</cim:GeneratingUnit.maxOperatingP>- Missing:
rdf:datatype="http://www.w3.org/2001/XMLSchema#decimal"
- Missing:
Applications cannot distinguish between strings, numbers, dates, etc., leading to validation errors and incorrect calculations.
How We Solved It¶
Schema-Based Type Registry System:
We built a two-layer resolution system that infers missing datatypes from CIM schema definitions:
- CimPropertyTypeRegistry - Singleton registry populated at startup with schema mappings:
public class CimPropertyTypeRegistry : ICimPropertyTypeRegistry
{
// Property name → datatype URI (e.g., "ACLineSegment.bch" → "Susceptance")
private readonly Dictionary<string, string> _propertyToDataType;
// CIMDatatype name → primitive type (e.g., "Susceptance" → "Float")
private readonly Dictionary<string, string> _cimDataTypes;
// Primitive type name → CimPrimitiveType enum
private readonly Dictionary<string, CimPrimitiveType> _primitives;
public bool TryGetPropertyDataType(string propertyName, out string dataTypeUri)
{
// Lookup property → datatype mapping from schema
return _propertyToDataType.TryGetValue(propertyName, out dataTypeUri);
}
public bool TryGetPrimitiveType(string cimDataType, out CimPrimitiveType primitiveType)
{
// Resolve CIMDatatype → primitive type chain
// e.g., "Susceptance" → "Float" → CimPrimitiveType.Float
if (_primitives.TryGetValue(cimDataType, out primitiveType))
return true;
if (_cimDataTypes.TryGetValue(cimDataType, out var valueType))
return TryGetPrimitiveType(valueType, out primitiveType);
return false;
}
}
- CimPropertyTypeResolver - Resolves property names to XSD datatypes:
public class CimPropertyTypeResolver : ICimPropertyTypeResolver
{
private readonly ICimPropertyTypeRegistry _registry;
public bool TryResolveDataType(string propertyName, out string? xsdDataType)
{
// Step 1: Property name → CIM datatype
if (!_registry.TryGetPropertyDataType(propertyName, out var dataType))
return false;
// Step 2: CIM datatype → Primitive type
if (!_registry.TryGetPrimitiveType(dataType, out var primitiveType))
return false;
// Step 3: Primitive type → XSD URI
xsdDataType = primitiveType switch
{
CimPrimitiveType.Float => "http://www.w3.org/2001/XMLSchema#float",
CimPrimitiveType.Integer => "http://www.w3.org/2001/XMLSchema#integer",
CimPrimitiveType.Boolean => "http://www.w3.org/2001/XMLSchema#boolean",
CimPrimitiveType.DateTime => "http://www.w3.org/2001/XMLSchema#dateTime",
// ... other mappings
_ => null
};
return xsdDataType != null;
}
}
- Integrated in CimPropertyFactory - Automatically enriches properties during parsing:
public class CimPropertyFactory : ICimPropertyFactory
{
protected ICimPropertyTypeResolver TypeResolver { get; }
public virtual CimLiteralProperty GetLiteralProperty(
string propertyName,
ILiteralNode literalNode)
{
// Use existing datatype if present in the literal
var dataType = literalNode.DataType?.ToString();
// If no datatype in literal, try to resolve from schema registry
if (string.IsNullOrEmpty(dataType) &&
TypeResolver.TryResolveDataType(propertyName, out var schemaDataType))
{
dataType = schemaDataType;
}
return new CimLiteralProperty(
name: propertyName,
value: literalNode.Value,
dataType: dataType,
language: literalNode.Language
);
}
}
Resolution Chain Example:
Input: <cim:ACLineSegment.bch>0.0000005</cim:ACLineSegment.bch>
1. CimPropertyFactory detects missing rdf:datatype
2. TypeResolver.TryResolveDataType("ACLineSegment.bch", out xsdType)
- Registry lookup: "ACLineSegment.bch" → "Susceptance"
- Primitive lookup: "Susceptance" → CimPrimitiveType.Float
- XSD mapping: CimPrimitiveType.Float → "http://www.w3.org/2001/XMLSchema#float"
3. CimLiteralProperty created with inferred datatype
Output: Properly typed property that can be validated and processed correctly
Key Benefits:
- No Runtime Schema Queries: Registry pre-populated at startup for performance
- Handles CIMDatatype Chains: Resolves nested type references (CIMDatatype → value → Primitive)
- Graceful Fallback: If type resolution fails, property still created without datatype
- Standard XSD Output: Converts CIM types to W3C standard XSD datatypes for interoperability
3. No Standard Way to Handle Multiple Profiles/Versions¶
Root Cause Analysis¶
- Complex Ecosystem: CGMES has multiple versions (v2.4.15, v3.0) and profiles (EQ, SSH, TP, SV, etc.)
- Missing Machinery: No standard way to:
- Validate against specific profile versions
- Convert between versions
- Handle backward/forward compatibility
Vendor tools implement different validation rules, causing interoperability failures.
4. Lack of Open, Standardized Tooling¶
Root Cause Analysis¶
- Vendor Lock-in: Each vendor developed proprietary parsers with different interpretations
- Duplicated Effort: 40+ TSOs and their vendors all solving the same problems independently
- No Reference Implementation: IEC/ENTSO-E published standards but no reference code
5. Poor Validation & Debugging Experience¶
Root Cause Analysis¶
- Legacy Validation: Originally used OCL (Object Constraint Language), hard to maintain
- No Standard Validation Reports: Each tool produces different error formats
- Hard to Debug: When validation fails, difficult to trace which profile/rule caused it