Text property XML: writer emits properties and values its own reader rejects (record fails to load)
评估
调研方向
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, andprop_NinsideBulNumFontInfo. Existing files that now fail to load will open again. - The writer emits only what older readers already accept. It writes
marginTop. It writesbulCusTxtfor 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
FwTextPropTypeconstant through both serializers. A guard test fails when a new constant has no classification.
- 主要语言
- C#
- 星标
- 3
- 派生
- 15
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
sillsdev/liblcm 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 54/100
-
Saving run text that contains a lone (unpaired) surrogate throws in TsString normalization可能已有人在做 @johnml1135 于 1 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 30/100
-
Text props: an unknown writing-system handle is saved as ws="", which no reader can load可能已有人在做 @johnml1135 于 1 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 25/100
-
难度 4/5 3-5 天 新手友好度 68/100
-
难度 4/5 3-5 天 新手友好度 38/100
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 68/100
Facepunch/sbox-public#12305 ·
维护者通常 5 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
JiaFeiMiao-K-Cat/DiscImageStudio#205 ·
维护者通常 1 天内回复
-
bug keep-fresh
难度 2/5 1-3 小时 新手友好度 68/100
Flow-Launcher/Flow.Launcher#4744 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
flyingpie/windows-terminal-quake#419 ·
维护者通常 1 天内回复
-
enhancement help wanted
难度 2/5 1-3 小时 新手友好度 82/100