jvs-pptxtojson 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc.cjs +15 -0
- package/.eslintignore +3 -0
- package/.eslintrc.cjs +78 -0
- package/PPTX_OOXML_/350/247/243/346/236/220/345/256/214/346/225/264/350/257/264/346/230/216.md +538 -0
- package/README.md +248 -243
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/favicon.ico +0 -0
- package/index.html +553 -0
- package/package.json +48 -55
- package/parsed_result.json +35569 -0
- package/pptx_standard_xml.txt +451 -0
- package/rollup.config.js +50 -0
- package/src/animation.js +81 -0
- package/src/border.js +156 -0
- package/src/chart.js +227 -0
- package/src/color.js +178 -0
- package/src/constants.js +3 -0
- package/src/diagram.js +132 -0
- package/src/fill.js +936 -0
- package/src/fontStyle.js +253 -0
- package/src/math.js +184 -0
- package/src/paragraph.js +253 -0
- package/src/position.js +32 -0
- package/src/pptxtojson.js +1361 -0
- package/src/readXmlFile.js +52 -0
- package/src/schemeColor.js +56 -0
- package/src/shadow.js +19 -0
- package/src/shape.js +539 -0
- package/src/shapePath.js +4637 -0
- package/src/table.js +207 -0
- package/src/text.js +228 -0
- package/src/textInsets.js +64 -0
- package/src/utils.js +202 -0
- package/test_parse.js +34 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
package/.babelrc.cjs
ADDED
package/.eslintignore
ADDED
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
env: {
|
|
3
|
+
node: true,
|
|
4
|
+
browser: true,
|
|
5
|
+
es6: true,
|
|
6
|
+
},
|
|
7
|
+
extends: [
|
|
8
|
+
'eslint:recommended',
|
|
9
|
+
],
|
|
10
|
+
parserOptions: {
|
|
11
|
+
ecmaVersion: 2020,
|
|
12
|
+
sourceType: 'module',
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
'curly': ['error', 'multi-line'],
|
|
16
|
+
'eqeqeq': ['error', 'always'],
|
|
17
|
+
'semi': ['error', 'never'],
|
|
18
|
+
'indent': ['error', 2, {
|
|
19
|
+
'SwitchCase': 1,
|
|
20
|
+
}],
|
|
21
|
+
'quotes': ['error', 'single', {
|
|
22
|
+
'avoidEscape': true,
|
|
23
|
+
'allowTemplateLiterals': true,
|
|
24
|
+
}],
|
|
25
|
+
'key-spacing': ['error', {
|
|
26
|
+
'beforeColon': false,
|
|
27
|
+
'afterColon': true,
|
|
28
|
+
'mode': 'strict',
|
|
29
|
+
}],
|
|
30
|
+
'no-empty': 'error',
|
|
31
|
+
'no-else-return': 'error',
|
|
32
|
+
'no-multi-spaces': 'error',
|
|
33
|
+
'require-await': 'error',
|
|
34
|
+
'brace-style': ['error', 'stroustrup'],
|
|
35
|
+
'spaced-comment': ['error', 'always'],
|
|
36
|
+
'arrow-spacing': 'error',
|
|
37
|
+
'no-duplicate-imports': 'error',
|
|
38
|
+
'comma-spacing': ['error', {
|
|
39
|
+
'before': false,
|
|
40
|
+
'after': true,
|
|
41
|
+
}],
|
|
42
|
+
'default-case': 'error',
|
|
43
|
+
'consistent-this': ['error', '_this'],
|
|
44
|
+
'max-depth': ['error', 6],
|
|
45
|
+
'max-lines': ['error', 2000],
|
|
46
|
+
'no-multi-str': 'error',
|
|
47
|
+
'space-infix-ops': 'error',
|
|
48
|
+
'space-before-blocks': ['error', 'always'],
|
|
49
|
+
'space-before-function-paren': ['error', {
|
|
50
|
+
'named': 'never',
|
|
51
|
+
'anonymous': 'never',
|
|
52
|
+
'asyncArrow': 'always',
|
|
53
|
+
}],
|
|
54
|
+
'keyword-spacing': ['error'],
|
|
55
|
+
'prefer-const': 'error',
|
|
56
|
+
'no-useless-return': 'error',
|
|
57
|
+
'array-bracket-spacing': 'error',
|
|
58
|
+
'no-useless-escape': 'off',
|
|
59
|
+
'no-case-declarations': 'off',
|
|
60
|
+
'no-eval': 'error',
|
|
61
|
+
'no-var': 'error',
|
|
62
|
+
'no-with': 'error',
|
|
63
|
+
'no-alert': 'warn',
|
|
64
|
+
'no-console': 'warn',
|
|
65
|
+
'no-debugger': 'warn',
|
|
66
|
+
},
|
|
67
|
+
overrides: [
|
|
68
|
+
{
|
|
69
|
+
files: [
|
|
70
|
+
'**/__tests__/*.{j,t}s?(x)',
|
|
71
|
+
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
|
72
|
+
],
|
|
73
|
+
env: {
|
|
74
|
+
jest: true,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
}
|
package/PPTX_OOXML_/350/247/243/346/236/220/345/256/214/346/225/264/350/257/264/346/230/216.md
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
# PPTX OOXML 解析完整说明
|
|
2
|
+
|
|
3
|
+
> 基于 ISO/IEC 29500-1 (ECMA-376) Part 1 — PresentationML + DrawingML
|
|
4
|
+
> 适用场景:PPTX 解析器开发、PPTX → JSON/XML 转换、在线 PPT 渲染引擎
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 一、命名空间(解析时务必保留)
|
|
9
|
+
|
|
10
|
+
| 前缀 | URI | 用途 |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `p:` | `http://schemas.openxmlformats.org/presentationml/2006/main` | PresentationML(幻灯片、形状树、母版等) |
|
|
13
|
+
| `a:` | `http://schemas.openxmlformats.org/drawingml/2006/main` | DrawingML(填充、线条、颜色、文本、表格) |
|
|
14
|
+
| `r:` | `http://schemas.openxmlformats.org/officeDocument/2006/relationships` | 关系 ID 引用(embed/link) |
|
|
15
|
+
| `c:` | `http://schemas.openxmlformats.org/drawingml/2006/chart` | 图表数据 |
|
|
16
|
+
| `dgm:` | `http://schemas.openxmlformats.org/drawingml/2006/diagram` | SmartArt / 关系图 |
|
|
17
|
+
| `v:` | `urn:schemas-microsoft-com:vml` | 旧版 VML(极少数兼容场景) |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 二、PPTX 包结构(解析入口)
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
[pptx]
|
|
25
|
+
├── [Content_Types].xml ← MIME 类型注册表
|
|
26
|
+
├── _rels/.rels ← 包级关系
|
|
27
|
+
├── ppt/
|
|
28
|
+
│ ├── presentation.xml ← p:presentation(根节点)
|
|
29
|
+
│ ├── _rels/presentation.xml.rels
|
|
30
|
+
│ ├── slides/
|
|
31
|
+
│ │ ├── slide{N}.xml ← p:sld(每页幻灯片)
|
|
32
|
+
│ │ └── _rels/slide{N}.xml.rels
|
|
33
|
+
│ ├── slideMasters/
|
|
34
|
+
│ │ └── slideMaster{N}.xml ← 母版定义
|
|
35
|
+
│ ├── slideLayouts/
|
|
36
|
+
│ │ └── slideLayout{N}.xml ← 版式定义
|
|
37
|
+
│ ├── theme/
|
|
38
|
+
│ │ └── theme{N}.xml ← a:theme(配色/字体/效果矩阵)
|
|
39
|
+
│ ├── notesSlides/
|
|
40
|
+
│ │ └── notesSlide{N}.xml ← 演讲者备注
|
|
41
|
+
│ ├── tables/ ← 表格样式(若有)
|
|
42
|
+
│ └── media/
|
|
43
|
+
│ └── image{N}.{ext} ← 图片/音频/视频资源
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 关键文件说明
|
|
47
|
+
|
|
48
|
+
| 文件 | 解析优先级 | 作用 |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `[Content_Types].xml` | ⭐⭐⭐ | 所有部件的 MIME 类型注册,解析入口 |
|
|
51
|
+
| `_rels/.rels` | ⭐⭐⭐ | 包级关系,定位 presentation.xml |
|
|
52
|
+
| `presentation.xml` | ⭐⭐⭐ | 幻灯片顺序、页面尺寸、默认样式 |
|
|
53
|
+
| `slide{N}.xml` | ⭐⭐⭐ | 每页具体内容(形状/文本/图片/表格) |
|
|
54
|
+
| `slideMaster{N}.xml` | ⭐⭐ | 母版占位符、默认样式继承 |
|
|
55
|
+
| `slideLayout{N}.xml` | ⭐⭐ | 版式细节,继承母版 |
|
|
56
|
+
| `theme{N}.xml` | ⭐⭐⭐ | 配色方案(clrScheme)、字体方案(fontScheme)、效果方案(fmtScheme) |
|
|
57
|
+
| `notesSlide{N}.xml` | ⭐ | 演讲者备注文本 |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 三、幻灯片 XML 结构(p:sld → p:spTree)
|
|
62
|
+
|
|
63
|
+
### 3.1 幻灯片整体结构
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<p:sld>
|
|
67
|
+
<p:cSld> <!-- Common Slide Data -->
|
|
68
|
+
<p:spTree> <!-- 形状树(最重要) -->
|
|
69
|
+
<p:nvGrpSpPr/> <!-- 组形状非可视属性 -->
|
|
70
|
+
<p:grpSpPr/> <!-- 组形状变换 -->
|
|
71
|
+
<p:sp> ... </p:sp> <!-- 形状/文本框/占位符 -->
|
|
72
|
+
<p:pic> ... </p:pic> <!-- 图片 -->
|
|
73
|
+
<p:graphicFrame> ... <!-- 表格/图表/OLE 对象 -->
|
|
74
|
+
<p:cxnSp> ... </p:cxnSp><!-- 连接符(箭头线) -->
|
|
75
|
+
<p:grpSp> ... </p:grpSp><!-- 组合形状(递归) -->
|
|
76
|
+
</p:spTree>
|
|
77
|
+
</p:cSld>
|
|
78
|
+
<p:clrMapOvr/> <!-- 可选:覆盖主题配色 -->
|
|
79
|
+
<p:timing/> <!-- 动画(通常跳过) -->
|
|
80
|
+
</p:sld>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3.2 `<p:sp>`(形状)三大子元素
|
|
84
|
+
|
|
85
|
+
| 子元素 | 标签路径 | 解析重点 |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| 非可视属性 | `<p:nvSpPr>` → `<p:cNvPr id name/>` `<p:nvPr ph=""/>` | id / 名称 / 是否为标题/正文占位符 |
|
|
88
|
+
| **可视属性** | `<p:spPr>` | ⭐ 几何 / 位置 / 填充 / 线条 / 效果 / 变换 |
|
|
89
|
+
| 文本体 | `<p:txBody>` | ⭐ 段落 / 运行 / 字体 / 文字颜色 |
|
|
90
|
+
|
|
91
|
+
### 3.3 `<p:pic>`(图片)
|
|
92
|
+
|
|
93
|
+
```xml
|
|
94
|
+
<p:pic>
|
|
95
|
+
<p:nvPicPr>
|
|
96
|
+
<p:cNvPr id="4" name="Picture 3"/>
|
|
97
|
+
<p:nvPr/>
|
|
98
|
+
</p:nvPicPr>
|
|
99
|
+
<p:blipFill>
|
|
100
|
+
<a:blip r:embed="rId2"/> <!-- 查 _rels/slideN.xml.rels 得 media/xxx.png -->
|
|
101
|
+
<a:srcRect l="10000" t="10000" r="10000" b="10000"/> <!-- 裁剪(万分之一) -->
|
|
102
|
+
<a:stretch/> <!-- 拉伸模式 -->
|
|
103
|
+
</p:blipFill>
|
|
104
|
+
<p:spPr> <!-- 位置/尺寸 -->
|
|
105
|
+
<a:xfrm>
|
|
106
|
+
<a:off x="3657600" y="2743200"/>
|
|
107
|
+
<a:ext cx="5486400" cy="3657600"/>
|
|
108
|
+
</a:xfrm>
|
|
109
|
+
</p:spPr>
|
|
110
|
+
</p:pic>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3.4 `<p:graphicFrame>`(表格/图表)
|
|
114
|
+
|
|
115
|
+
```xml
|
|
116
|
+
<p:graphicFrame>
|
|
117
|
+
<p:nvGraphicFramePr>...</p:nvGraphicFramePr>
|
|
118
|
+
<p:xfrm>...</p:xfrm>
|
|
119
|
+
<a:graphic>
|
|
120
|
+
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
|
|
121
|
+
<a:tbl> ... </a:tbl> <!-- 表格内容 -->
|
|
122
|
+
</a:graphicData>
|
|
123
|
+
</a:graphic>
|
|
124
|
+
</p:graphicFrame>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 四、`<p:spPr>` —— 填充 / 线条 / 几何 / 变换(DrawingML a:)
|
|
130
|
+
|
|
131
|
+
### 4.1 变换与几何
|
|
132
|
+
|
|
133
|
+
| 标签 | 属性/子元素 | 说明 |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `<a:xfrm rot="..." flipH/V="1">` | `<a:off x="..." y="..."/>` | 旋转(1° = 60000 EMU)、翻转、位置 |
|
|
136
|
+
| | `<a:ext cx="..." cy="..."/>` | 尺寸(EMU) |
|
|
137
|
+
| `<a:prstGeom prst="rect">` | `<a:avLst/>` | 预设几何:rect(矩形)、ellipse(椭圆)、roundRect(圆角矩形)、triangle(三角形)、arrow(箭头)等 |
|
|
138
|
+
| `<a:custGeom>` | `<a:pathLst><a:path>` | 自定义贝塞尔路径 |
|
|
139
|
+
|
|
140
|
+
### 4.2 填充类型(互斥,取第一个有效)
|
|
141
|
+
|
|
142
|
+
| 标签 | 子颜色节点 | 说明 |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `<a:noFill/>` | — | 无填充 / 透明 |
|
|
145
|
+
| `<a:solidFill>` | `<a:srgbClr val="RRGGBB"/>` 或 `<a:schemeClr val="accent1"/>` | ⭐ 纯色填充 |
|
|
146
|
+
| `<a:gradFill>` | `<a:gsLst><a:gs pos="50000"><a:srgbClr/></a:gs></a:gsLst>` `<a:lin ang="5400000"/>` | 线性/径向渐变(pos 单位万分之一,ang 单位 1°=60000) |
|
|
147
|
+
| `<a:blipFill>` | `<a:blip r:embed="rIdX"/>` | 图片填充(查 rels 得图片路径) |
|
|
148
|
+
| `<a:pattFill>` | `<a:fgClr>` + `<a:bgClr>` | 图案填充 |
|
|
149
|
+
| `<a:grpFill/>` | — | 继承组合填充 |
|
|
150
|
+
|
|
151
|
+
### 4.3 线条(轮廓)`<a:ln w="EMU">`
|
|
152
|
+
|
|
153
|
+
| 子元素 | 说明 |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `<a:noFill/>`(在 ln 内)| 无边框 |
|
|
156
|
+
| `<a:solidFill>` / `<a:gradFill>` | 线颜色(同填充规则) |
|
|
157
|
+
| `<a:prstDash val="solid\|dot\|dash\|lgDash\|dashDot"/>` | 虚线样式 |
|
|
158
|
+
| `<a:round/>` `<a:miter/>` `<a:bevel/>` | 转角样式 |
|
|
159
|
+
| `<a:cap val="flat\|round\|square"/>` | 线端样式 |
|
|
160
|
+
| `<a:cmpd val="sng\|dbl\|thickThin"/>` | 复合线(单线/双线/粗细变化) |
|
|
161
|
+
| `<a:headEnd type="arrow" w="med" len="med"/>` | 线头箭头 |
|
|
162
|
+
| `<a:tailEnd type="arrow" w="med" len="med"/>` | 线尾箭头 |
|
|
163
|
+
|
|
164
|
+
> ⚠️ 若 `<a:ln>` 不存在但 `<p:style><a:lnRef idx="N"/>` 存在 → 查 `theme1.xml → a:lnStyleLst[idx-1]` 取默认线型/颜色
|
|
165
|
+
|
|
166
|
+
### 4.4 效果
|
|
167
|
+
|
|
168
|
+
| 标签 | 子元素 | 说明 |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| `<a:effectLst>` | 容器 | 效果列表 |
|
|
171
|
+
| `<a:outerShdw>` | `<a:srgbClr>` + `blurRad` + `dist` + `dir` | 外阴影 |
|
|
172
|
+
| `<a:innerShdw>` | 同上 | 内阴影 |
|
|
173
|
+
| `<a:glow>` | `<a:srgbClr>` + `rad` | 发光效果 |
|
|
174
|
+
| `<a:reflection>` | `blurRad` + `stDist` + `endPos` + `fadeDir` | 反射效果 |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 五、颜色模型(DrawingML a: 颜色系统 —— 解析关键)
|
|
179
|
+
|
|
180
|
+
PPT 颜色可能是直接 RGB 或**主题配色引用 + 变换**:
|
|
181
|
+
|
|
182
|
+
### 5.1 颜色节点类型
|
|
183
|
+
|
|
184
|
+
| 标签 | 含义 | 查主题位置 |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| `<a:srgbClr val="FF5733"/>` | 直接 RGB(不含 `#`)| — |
|
|
187
|
+
| `<a:schemeClr val="accent1\|accent2\|...\|tx1\|bg1\|dk1\|lt1"/>` | 引用主题配色 | `a:theme/a:themeElements/a:clrScheme/` |
|
|
188
|
+
| `<a:sysClr val="window\|windowText" lastClr="RRGGBB"/>` | 系统颜色(极少用)| — |
|
|
189
|
+
| `<a:hslClr hue="..." sat="..." lum="..."/>` | HSL 颜色 | — |
|
|
190
|
+
| `<a:prstClr val="black\|white\|red"/>` | 预设颜色名 | — |
|
|
191
|
+
|
|
192
|
+
### 5.2 颜色变换(子节点)
|
|
193
|
+
|
|
194
|
+
| 标签 | 含义 | 示例 |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| `<a:lumMod val="50000"/>` | 亮度调制(×50%)| 作用于 schemeClr |
|
|
197
|
+
| `<a:lumOff val="20000"/>` | 亮度偏移(+20%)| — |
|
|
198
|
+
| `<a:shade val="50000"/>` | 暗化(×50%)| — |
|
|
199
|
+
| `<a:tint val="80000"/>` | 减淡(×80%)| — |
|
|
200
|
+
| `<a:alpha val="50000"/>` | 透明度(50000 = 50% 不透明)| — |
|
|
201
|
+
| `<a:satMod val="130000"/>` | 饱和度调制(×130%)| — |
|
|
202
|
+
| `<a:hueMod val="60000"/>` | 色相调制 | — |
|
|
203
|
+
|
|
204
|
+
### 5.3 主题配色方案(theme1.xml 中)
|
|
205
|
+
|
|
206
|
+
```xml
|
|
207
|
+
<a:clrScheme name="Office">
|
|
208
|
+
<a:dk1><a:sysClr val="window" lastClr="FFFFFF"/></a:dk1> <!-- 深色1 / 背景1 -->
|
|
209
|
+
<a:lt1><a:sysClr val="windowText" lastClr="000000"/></a:lt1><!-- 浅色1 / 文字1 -->
|
|
210
|
+
<a:dk2><a:srgbClr val="1F4E79"/></a:dk2> <!-- 深色2 -->
|
|
211
|
+
<a:lt2><a:srgbClr val="D6E4F0"/></a:lt2> <!-- 浅色2 -->
|
|
212
|
+
<a:accent1><a:srgbClr val="4472C4"/></a:accent1> <!-- 强调色1~6 -->
|
|
213
|
+
<a:accent2><a:srgbClr val="ED7D31"/></a:accent2>
|
|
214
|
+
<a:accent3><a:srgbClr val="A5A5A5"/></a:accent3>
|
|
215
|
+
<a:accent4><a:srgbClr val="FFC000"/></a:accent4>
|
|
216
|
+
<a:accent5><a:srgbClr val="5B9BD5"/></a:accent5>
|
|
217
|
+
<a:accent6><a:srgbClr val="70AD47"/></a:accent6>
|
|
218
|
+
<a:hlink><a:srgbClr val="0563C1"/></a:hlink> <!-- 超链接 -->
|
|
219
|
+
<a:folHlink><a:srgbClr val="954F72"/></a:folHlink> <!-- 已访问链接 -->
|
|
220
|
+
</a:clrScheme>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 5.4 颜色解析算法(伪代码)
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
function resolveColor(node):
|
|
227
|
+
if node has a:srgbClr:
|
|
228
|
+
color = srgbClr.val
|
|
229
|
+
else if node has a:schemeClr:
|
|
230
|
+
schemeName = schemeClr.val
|
|
231
|
+
color = theme.clrScheme[schemeName].srgbClr.val
|
|
232
|
+
else:
|
|
233
|
+
return FALLBACK_COLOR
|
|
234
|
+
|
|
235
|
+
// 应用变换链
|
|
236
|
+
for child in node.children:
|
|
237
|
+
if child is a:lumMod: color = applyLuminanceMod(color, child.val)
|
|
238
|
+
if child is a:lumOff: color = applyLuminanceOffset(color, child.val)
|
|
239
|
+
if child is a:shade: color = applyShade(color, child.val)
|
|
240
|
+
if child is a:tint: color = applyTint(color, child.val)
|
|
241
|
+
if child is a:alpha: alpha = child.val
|
|
242
|
+
|
|
243
|
+
return { rgb: color, alpha: alpha }
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 5.5 单位速记
|
|
247
|
+
|
|
248
|
+
| 单位 | 换算 |
|
|
249
|
+
|---|---|
|
|
250
|
+
| 1 英寸 | 914,400 EMU |
|
|
251
|
+
| 1 厘米 | 360,000 EMU |
|
|
252
|
+
| 1 磅 (pt) | 12,700 EMU |
|
|
253
|
+
| 1°(角度)| 60,000(用于 rot / ang 属性) |
|
|
254
|
+
| 百分比 | 50,000 = 50%(万分之一为单位) |
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 六、文本(`<p:txBody>` —— DrawingML a:)
|
|
259
|
+
|
|
260
|
+
### 6.1 文本整体结构
|
|
261
|
+
|
|
262
|
+
```xml
|
|
263
|
+
<p:txBody>
|
|
264
|
+
<a:bodyPr anchor="t|c|b" wrap="square" vert="horz"/>
|
|
265
|
+
<a:lstStyle/> <!-- 列表级别样式引用 -->
|
|
266
|
+
<a:p> <!-- 段落 -->
|
|
267
|
+
<a:pPr lvl="0" algn="l|c|r|j">
|
|
268
|
+
<a:buFont typeface="..."/>
|
|
269
|
+
<a:buChar char="•"/>
|
|
270
|
+
<a:spcBef val="..."/> <!-- 段前距 (EMU) -->
|
|
271
|
+
<a:spcAft val="..."/> <!-- 段后距 (EMU) -->
|
|
272
|
+
<a:lnSpc val="..."/> <!-- 行距 (EMU) -->
|
|
273
|
+
</a:pPr>
|
|
274
|
+
<a:r> <!-- 文本运行 (Run) -->
|
|
275
|
+
<a:rPr lang="zh-CN" sz="1800" b="1" i="1" u="sng">
|
|
276
|
+
<a:solidFill>
|
|
277
|
+
<a:srgbClr val="333333"/>
|
|
278
|
+
</a:solidFill>
|
|
279
|
+
</a:rPr>
|
|
280
|
+
<a:t>实际文字内容</a:t>
|
|
281
|
+
</a:r>
|
|
282
|
+
<a:br/> <!-- 软换行 -->
|
|
283
|
+
</a:p>
|
|
284
|
+
</p:txBody>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 6.2 运行属性(`<a:rPr>`)
|
|
288
|
+
|
|
289
|
+
| 属性 | 说明 | 值示例 |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `lang` | 语言 | `zh-CN` / `en-US` |
|
|
292
|
+
| `sz` | 字号(百分之一磅)| 1800 = 18pt |
|
|
293
|
+
| `b="1"` | 粗体 | 0/1 |
|
|
294
|
+
| `i="1"` | 斜体 | 0/1 |
|
|
295
|
+
| `u="sng\|dbl\|none"` | 下划线 | sng=单线 |
|
|
296
|
+
| `strike="sng\|dbl\|noStrike"` | 删除线 | — |
|
|
297
|
+
| `caps="all\|small"` | 大小写 | all=全大写 |
|
|
298
|
+
| `spc="200"` | 字符间距(EMU)| 正数=加宽,负数=紧缩 |
|
|
299
|
+
|
|
300
|
+
### 6.3 文字颜色
|
|
301
|
+
|
|
302
|
+
文字颜色同第五节规则,位于 `<a:rPr>` 内:
|
|
303
|
+
|
|
304
|
+
```xml
|
|
305
|
+
<a:rPr sz="1800" b="1">
|
|
306
|
+
<a:solidFill>
|
|
307
|
+
<a:srgbClr val="FF0000"/> <!-- 直接 RGB -->
|
|
308
|
+
</a:solidFill>
|
|
309
|
+
</a:rPr>
|
|
310
|
+
|
|
311
|
+
<a:rPr sz="1400">
|
|
312
|
+
<a:solidFill>
|
|
313
|
+
<a:schemeClr val="accent1"> <!-- 主题配色引用 -->
|
|
314
|
+
<a:lumMod val="50000"/>
|
|
315
|
+
</a:schemeClr>
|
|
316
|
+
</a:solidFill>
|
|
317
|
+
</a:rPr>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
> 若无 `<a:rPr>` 中颜色 → 继承段落 `<a:pPr>` → 占位符 → 主题默认文字色
|
|
321
|
+
|
|
322
|
+
### 6.4 段落属性(`<a:pPr>`)
|
|
323
|
+
|
|
324
|
+
| 属性/子元素 | 说明 |
|
|
325
|
+
|---|---|
|
|
326
|
+
| `algn="l\|c\|r\|j"` | 对齐:左/中/右/两端对齐 |
|
|
327
|
+
| `lvl="0"` | 列表层级(0~8)|
|
|
328
|
+
| `marL` / `marR` | 左右缩进 (EMU) |
|
|
329
|
+
| `indent` | 首行缩进 (EMU) |
|
|
330
|
+
| `spcBef` / `spcAft` | 段前/段后距 (EMU) |
|
|
331
|
+
| `lnSpc` | 行距 (EMU) |
|
|
332
|
+
| `<a:buChar char="•"/>` | 项目符号字符 |
|
|
333
|
+
| `<a:buFont typeface="..."/>` | 项目符号字体 |
|
|
334
|
+
| `<a:buNone/>` | 无项目符号 |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 七、表格(`<a:tbl>` in `<p:graphicFrame>`)
|
|
339
|
+
|
|
340
|
+
### 7.1 表格结构
|
|
341
|
+
|
|
342
|
+
```xml
|
|
343
|
+
<a:tbl>
|
|
344
|
+
<a:tblPr firstRow="1" bandRow="1" bandCol="0">
|
|
345
|
+
<a:tableStyleId>{GUID}</a:tableStyleId>
|
|
346
|
+
</a:tblPr>
|
|
347
|
+
<a:tblGrid>
|
|
348
|
+
<a:gridCol w="3048000"/> <!-- 列宽 (EMU) -->
|
|
349
|
+
<a:gridCol w="3048000"/>
|
|
350
|
+
</a:tblGrid>
|
|
351
|
+
<a:tr h="568000"> <!-- 行高 (EMU) -->
|
|
352
|
+
<a:tc> <!-- 单元格 -->
|
|
353
|
+
<a:txBody>... </a:txBody> <!-- 同第六节文本 -->
|
|
354
|
+
<a:tcPr rowSpan="2" colSpan="1">
|
|
355
|
+
<a:fill> <!-- 单元格填充 -->
|
|
356
|
+
<a:solidFill>
|
|
357
|
+
<a:srgbClr val="D6E4F0"/>
|
|
358
|
+
</a:solidFill>
|
|
359
|
+
</a:fill>
|
|
360
|
+
</a:tcPr>
|
|
361
|
+
</a:tc>
|
|
362
|
+
</a:tr>
|
|
363
|
+
</a:tbl>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 7.2 表格属性说明
|
|
367
|
+
|
|
368
|
+
| 元素/属性 | 说明 |
|
|
369
|
+
|---|---|
|
|
370
|
+
| `<a:tblPr firstRow="1">` | 是否应用首行样式(斑马纹) |
|
|
371
|
+
| `<a:tblPr bandRow="1">` | 是否应用隔行样式 |
|
|
372
|
+
| `<a:tblPr bandCol="1">` | 是否应用隔列样式 |
|
|
373
|
+
| `<a:tableStyleId>` | 表格样式 GUID,查 `ppt/tableStyles.xml` |
|
|
374
|
+
| `<a:tcPr rowSpan / colSpan>` | 单元格合并 |
|
|
375
|
+
| `<a:tcPr horzOverflow="clip\|overflow"` | 水平溢出处理 |
|
|
376
|
+
| `<a:tcPr anchor="t\|c\|b"` | 垂直对齐 |
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## 八、主题继承解析顺序(最重要!)
|
|
381
|
+
|
|
382
|
+
当 `<p:spPr>` 中某属性(fill / ln / 字体)**缺失时**,按此优先级解析:
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
spPr 显式值(最高优先级)
|
|
386
|
+
↓(无)
|
|
387
|
+
p:style → fillRef/lnRef/fontRef idx → theme1.xml fillStyleLst/lnStyleLst/fontScheme
|
|
388
|
+
↓(无)
|
|
389
|
+
slideLayout → 对应 placeholder 样式
|
|
390
|
+
↓(无)
|
|
391
|
+
slideMaster → 对应 placeholder 样式
|
|
392
|
+
↓(无)
|
|
393
|
+
presentation.xml → p:defaultTextStyle / p:defaultMasterStyle
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### 8.1 继承链详细展开
|
|
397
|
+
|
|
398
|
+
#### 第一层:spPr 显式值
|
|
399
|
+
```xml
|
|
400
|
+
<p:sp>
|
|
401
|
+
<p:spPr>
|
|
402
|
+
<a:solidFill><a:srgbClr val="FF0000"/></a:solidFill> <!-- 显式红色填充 -->
|
|
403
|
+
</p:spPr>
|
|
404
|
+
</p:sp>
|
|
405
|
+
```
|
|
406
|
+
→ 直接使用,不查继承链。
|
|
407
|
+
|
|
408
|
+
#### 第二层:p:style → theme 引用
|
|
409
|
+
```xml
|
|
410
|
+
<p:sp>
|
|
411
|
+
<p:style>
|
|
412
|
+
<a:fillRef idx="2"/> <!-- 查 theme1.xml → a:fillStyleLst[1] -->
|
|
413
|
+
<a:lnRef idx="1"/> <!-- 查 theme1.xml → a:lnStyleLst[0] -->
|
|
414
|
+
<a:fontRef idx="1"/> <!-- 查 theme1.xml → a:fontScheme/a:majorFont -->
|
|
415
|
+
</p:style>
|
|
416
|
+
</p:sp>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
theme1.xml 中:
|
|
420
|
+
```xml
|
|
421
|
+
<a:fmtScheme name="Office">
|
|
422
|
+
<a:fillStyleLst>
|
|
423
|
+
<a:solidFill><a:schemeClr val="bg1"/></a:solidFill> <!-- idx=1 -->
|
|
424
|
+
<a:solidFill><a:schemeClr val="accent1"/></a:solidFill> <!-- idx=2 -->
|
|
425
|
+
</a:fillStyleLst>
|
|
426
|
+
<a:lnStyleLst>
|
|
427
|
+
<a:ln w="12700">...</a:ln> <!-- idx=1 -->
|
|
428
|
+
</a:lnStyleLst>
|
|
429
|
+
</a:fmtScheme>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
#### 第三层:slideLayout 占位符样式
|
|
433
|
+
```xml
|
|
434
|
+
<!-- slideLayout1.xml -->
|
|
435
|
+
<p:sp ph="ctrTitle">
|
|
436
|
+
<p:spPr>
|
|
437
|
+
<a:solidFill><a:schemeClr val="tx1"/></a:solidFill>
|
|
438
|
+
</p:spPr>
|
|
439
|
+
</p:sp>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### 第四层:slideMaster 占位符样式
|
|
443
|
+
```xml
|
|
444
|
+
<!-- slideMaster1.xml -->
|
|
445
|
+
<p:sp ph="ctrTitle">
|
|
446
|
+
<p:spPr>
|
|
447
|
+
<a:solidFill><a:schemeClr val="dk1"/></a:solidFill>
|
|
448
|
+
</p:spPr>
|
|
449
|
+
</p:sp>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### 第五层:presentation.xml 默认值
|
|
453
|
+
```xml
|
|
454
|
+
<!-- presentation.xml -->
|
|
455
|
+
<p:defaultTextStyle>
|
|
456
|
+
<a:defPPr>
|
|
457
|
+
<a:defRPr sz="1800" b="0">
|
|
458
|
+
<a:solidFill><a:schemeClr val="tx1"/></a:solidFill>
|
|
459
|
+
</a:defRPr>
|
|
460
|
+
</a:defPPr>
|
|
461
|
+
</p:defaultTextStyle>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### 8.2 继承解析算法(伪代码)
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
function resolveProperty(shape, propertyName):
|
|
468
|
+
// Layer 1: 显式 spPr
|
|
469
|
+
if shape.spPr has propertyName:
|
|
470
|
+
return shape.spPr[propertyName]
|
|
471
|
+
|
|
472
|
+
// Layer 2: style → theme
|
|
473
|
+
if shape.style has reference for propertyName:
|
|
474
|
+
idx = shape.style[propertyName + "Ref"].idx
|
|
475
|
+
return theme.fmtScheme[propertyName + "StyleLst"][idx - 1]
|
|
476
|
+
|
|
477
|
+
// Layer 3: slideLayout placeholder
|
|
478
|
+
layoutShape = findMatchingPlaceholder(shape, slideLayout)
|
|
479
|
+
if layoutShape and layoutShape.spPr has propertyName:
|
|
480
|
+
return layoutShape.spPr[propertyName]
|
|
481
|
+
|
|
482
|
+
// Layer 4: slideMaster placeholder
|
|
483
|
+
masterShape = findMatchingPlaceholder(shape, slideMaster)
|
|
484
|
+
if masterShape and masterShape.spPr has propertyName:
|
|
485
|
+
return masterShape.spPr[propertyName]
|
|
486
|
+
|
|
487
|
+
// Layer 5: presentation default
|
|
488
|
+
return presentation.defaultStyle[propertyName]
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### 8.3 占位符匹配规则
|
|
492
|
+
|
|
493
|
+
占位符通过 `ph` 属性匹配:
|
|
494
|
+
|
|
495
|
+
| ph 值 | 含义 |
|
|
496
|
+
|---|---|
|
|
497
|
+
| `ctrTitle` | 中心标题 |
|
|
498
|
+
| `subTitle` | 副标题 |
|
|
499
|
+
| `body` | 正文 |
|
|
500
|
+
| `sldNum` | 幻灯片编号 |
|
|
501
|
+
| `ftr` | 页脚 |
|
|
502
|
+
| `hdr` | 页眉 |
|
|
503
|
+
| `dt` | 日期 |
|
|
504
|
+
| `obj` | 对象 |
|
|
505
|
+
| `chart` | 图表 |
|
|
506
|
+
| `tbl` | 表格 |
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## 附录:权威参考文档
|
|
511
|
+
|
|
512
|
+
| 资源 | 链接 |
|
|
513
|
+
|---|---|
|
|
514
|
+
| ISO/IEC 29500-1:2016 (ECMA-376 Part 1) | §19 PresentationML / §20 DrawingML |
|
|
515
|
+
| Open XML SDK 文档 | https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.presentation |
|
|
516
|
+
| OOXML 社区参考 | http://officeopenxml.com/prPresentation.php |
|
|
517
|
+
| W3ID OOXML 在线附录 | https://w3id.org/ooxml/onlineInfomativeAnnexes/ |
|
|
518
|
+
| DrawingML 颜色说明 | http://officeopenxml.com/drwSp-styles.php |
|
|
519
|
+
| LibreOffice OOXML 实现参考 | https://wiki.documentfoundation.org/Development/ODF/OOXML |
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 解析器建议实现顺序
|
|
524
|
+
|
|
525
|
+
1. **解压 ZIP** → 读 `[Content_Types].xml` + `_rels/.rels`
|
|
526
|
+
2. **解析 `presentation.xml`** → 建立幻灯片 ID ↔ rId ↔ 文件路径映射表
|
|
527
|
+
3. **解析 `theme/theme1.xml`** → 缓存 `clrScheme` / `fontScheme` / `fmtScheme`(fill/ln 样式列表)
|
|
528
|
+
4. **逐页解析 `slideN.xml`** → `spTree` 递归遍历 `sp` / `pic` / `graphicFrame` / `grpSp`
|
|
529
|
+
5. **对每个元素解析可视属性**:
|
|
530
|
+
- 先取 `spPr` 显式值
|
|
531
|
+
- 缺失则查 `style → theme` 继承链(第四节 + 第八节)
|
|
532
|
+
6. **颜色解析**:先 `srgbClr`,再 `schemeClr + theme.clrScheme + transform` 子节点(第五节)
|
|
533
|
+
7. **文本解析**:遍历 `txBody → p → r → rPr/t`(第六节)
|
|
534
|
+
8. **表格解析**:`graphicFrame → tbl → tr → tc`(第七节)
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
> 📌 **提示**:以上覆盖 PPTX 解析 95% 以上场景。动画(`<p:timing>`)、音频/视频、OLE 嵌入、数字签名等属于低频特性,可按需扩展。
|