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

未关闭
#409 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

@johnml1135 已经在做这个了。

开始于 2026年11月5日。

  • #410 来自 @johnml1135 —— 未关闭

评估

难度
5/5
预计耗时
一周以上
新手友好度
25/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
停滞
技术栈
csharp, xml
领域
backend, data

调研方向

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.

由索引模型根据 Issue 内容生成。

描述

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.
主要语言
C#
星标
3
派生
15
PR 合并指标
30 天内没有已合并 PR

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

sillsdev/liblcm 的其他 Issue

查看 sillsdev/liblcm 的全部 Issue

相似的 Issue

更多 C# Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。