Text property XML: writer emits properties and values its own reader rejects (record fails to load)

Abierto
#409 0 comentarios 0 reacciones 0 asignados Ver en GitHub

@johnml1135 ya está trabajando en esto.

Desde el 5/11/2026.

  • #410 de @johnml1135 — abierto

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
25/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Estancado
Stack tecnológico
csharp, xml
Área
backend, data

Línea de trabajo

Read TsPropsSerializer and TsStringSerializer in SIL.LCModel.Core, then inspect their readers and the existing writer and reader tests. Start by checking how each FwTextPropType is serialized and accepted, including malformed values. Add data driven round trip coverage for both serializers and a guard that classifies every property; done means released writer output remains readable, writer output round trips where supported, and malformed values do not throw.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

The text property XML writer and readers in SIL.LCModel.Core disagree. TsPropsSerializer (StyleRules) and TsStringSerializer (string runs) write some properties and values that their own readers reject with XmlSchemaException. They also write some properties that are dropped when read back.

Impact

When the reader rejects a record, CmObjectSurrogate reports a "corrupted record" and FieldWorks closes. The project then can't be opened until the data is fixed by hand. Properties that are dropped lose data silently on every save and load. For example, a custom bullet character (LT-16341) is never written, so it is lost on save.

Repro

Build an ITsTextProps (or a one-run ITsString) holding the property, serialize it with TsPropsSerializer.SerializePropsToXml (or TsStringSerializer.SerializeTsStringToXml), then deserialize the result.

var bldr = TsStringUtils.MakePropsBldr();
bldr.SetIntPropValues((int)FwTextPropType.ktptMarginTop, (int)FwTextPropVar.ktpvMilliPoint, 1500);
string xml = TsPropsSerializer.SerializePropsToXml(bldr.GetTextProps(), wsf); // <Prop MarginTop="1500">
TsPropsSerializer.DeserializePropsFromXml(xml, wsf); // XmlSchemaException: Unknown Prop attribute: MarginTop

Observed (current master, both serializers unless noted)

Property (number) Written as On read
ktptMarginTop (50) MarginTop throws; the reader only knows marginTop
ktptDirectionDepth (129), ktptHyphenate (150), ktptMaxLines (151), ktptCellBorderWidth (152), ktptCellSpacing (153), ktptCellPadding (154), ktptSetRowDefaults (159), ktptRelLineHeight (160) own name throws: unknown attribute
ktptEditable (155) editable throws in StyleRules; ignored on a run
ktptTabDef (23, int), ktptTabList (4), ktptCharStyle (2), ktptParaStyle (3) own name ignored (Debug.Fail in a Debug build)
ktptCustomBullet (7, string) nothing the custom bullet is lost on save (the reader accepts bulCusTxt, but the writer has no case)
ktptTableRule (161) nothing dropped on save
negative values: font size 6, offset 7 on a run (raised or lowered text), 19, 20, 128, 134-141, 143, 144, 148, 149, 162 -n throws: negative number not valid
values outside the enumeration: 2, 3, 4, 5, 17, 26 the number throws: invalid value
a variation other than mpt/rel on 6, 7, 24 fontsizeUnit="3" etc. throws: invalid unit
ktptLineHeight (24) = int.MinValue the writer throws OverflowException (Math.Abs)
ktptBulNumFontInfo (147) with a font name and font features (what BulletInfo encodes) the writer throws: NUL character in the attribute
ktptBulNumFontInfo (147) holding another int property prop_N throws: unknown attribute
ktptBulNumFontInfo (147) / ktptWsStyle (156), truncated the writer throws IndexOutOfRangeException
ktptObjData (6) with a GUID type but too short to hold a GUID the writer throws
string values holding characters XML can't represent the writer throws ArgumentException
ktptTags (5) shorter than one GUID tags="" loads as an empty tags property

There is no round-trip test, so nothing catches a mismatch. MarginTop is covered only by separate writer and reader tests, each pinning the other's spelling.

Proposed fix

  • The reader accepts everything a released writer has emitted. That covers MarginTop, the eight missing attribute names, negative numbers, numbers for enumerations and variations, and prop_N inside BulNumFontInfo. Existing files that now fail to load will open again.
  • The writer emits only what older readers already accept. It writes marginTop. It writes bulCusTxt for the custom bullet. It no longer writes tabDef, tabList, charStyle, paraStyle or editable: no reader has ever kept them, and nothing in liblcm or FieldWorks sets the first four. It still doesn't write ktptTableRule, because a new attribute name would make older readers reject the record.
  • The writer never throws on a value it holds. It leaves out a malformed binary value or a partial GUID. It strips characters XML can't represent, the same way it already does for run text. It decodes BulNumFontInfo string properties correctly.
  • Add a data-driven test that round-trips every FwTextPropType constant through both serializers. A guard test fails when a new constant has no classification.
Lenguaje dominante
C#
Estrellas
3
Forks
15
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de sillsdev/liblcm

Todos los issues de sillsdev/liblcm

Issues similares

Más issues de C#

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.