Docx转TinyMCE兼容HTML:段落缩进代码值与编辑器显示不符问题
解决ListParagraph段落缩进获取不到的问题
针对你遇到的ListParagraph样式段落缩进无法通过IndentationHanging/IndentationLeft获取的情况,核心原因是这类段落的缩进并非直接定义在段落本身,而是绑定到了列表编号的级别设置里,NPOI的段落属性不会自动同步这些值,得手动从编号定义里提取:
具体步骤
获取段落的编号关联信息
每个ListParagraph段落都会关联一个编号ID(numId)和级别ID(ilvl),先拿到这两个值:var paragraph = // 你的XWPFParagraph对象 var numId = paragraph.GetNumID(); var ilvl = paragraph.GetIndentLevel();从文档编号库中找到对应级别设置
文档的所有列表定义都存在Numbering部分,通过numId定位到具体编号,再通过ilvl找到对应级别:var numbering = doc.GetNumbering(); // doc是你的XWPFDocument对象 if (numbering == null || numId == null) return; var ctNum = numbering.GetCTNumbering().numList.FirstOrDefault(n => n.numId.val == numId); if (ctNum == null) return; // 找到对应级别,ilvl是从0开始的整数 var ctLvl = ctNum.lvl.FirstOrDefault(l => l.ilvl.val == ilvl);提取缩进值并转换单位
列表级别里的缩进定义在w:indent元素中,包含w:left(左缩进)、w:hanging(悬挂缩进)等属性,单位是Twip(1pt = 20 Twip),需要转换为目标单位:if (ctLvl?.indent != null) { // 左缩进:Twip转Pt var leftIndentTwip = ctLvl.indent.left?.val ?? 0; var leftIndentPt = leftIndentTwip / 20.0; // 悬挂缩进:Twip转Pt var hangingIndentTwip = ctLvl.indent.hanging?.val ?? 0; var hangingIndentPt = hangingIndentTwip / 20.0; // 这里就能拿到你看到的36pt左缩进、18pt悬挂缩进 }处理继承和默认情况
如果当前级别没有定义缩进,可能继承自父级别(比如ilvl-1),或者文档的默认列表设置,这时候可以递归往上查找级别,直到找到有缩进配置的项;如果还是没有,再检查ListParagraph样式的基础样式(比如Paragraph样式)的缩进属性。
额外注意
- NPOI对部分复杂XML节点没有封装成直接属性,需要直接操作CT(Core XML)对象读取原始结构,比如上面的
ctLvl.indent就是直接访问OOXML节点。 - 部分文档的列表可能用了
w:numPr里的w:startOverride等覆盖设置,要优先取段落自身的编号覆盖配置,再取全局编号定义。
内容的提问来源于stack exchange,提问作者kemsky
相关产品推荐
相关产品推荐

