CORE

描述符系统

声明式 XML 映射 — 描述符类型、构建器 API 和运行时函数

@office-open/core 的描述符系统提供 TypeScript Options 对象与 XML 之间的声明式双向映射。同一个描述符同时驱动序列化(Options → XML 字符串)和解析(Element → Options)。

描述符类型

每个描述符都是 CustomDescriptor<T>,手写 stringify()parse() 方法(无声明式属性/子元素构建器):

import type { CustomDescriptor } from "@office-open/core";

const myDesc: CustomDescriptor<MyOptions> = {
  kind: "custom",
  stringify(value, ctx) {
    return `<w:my val="${value.name}"/>`;
  },
  parse(el, ctx) {
    return { name: el.attributes?.["w:val"] } as MyOptions;
  },
};

高级用法: 当描述符的序列化输入类型与解析输出不同时(例如累加器式输入 vs. 结构化解析结果),需显式声明两者:CustomDescriptor<TInput, Ctx, TOutput>TOutput 默认为 TInput,因此常见的单参数形式 CustomDescriptor<T> 等价于 CustomDescriptor<T, WriteContext, T>

运行时函数

stringify()

将 Options 对象序列化为 XML 字符串:

import { stringify } from "@office-open/core";

const xml = stringify(myDesc, { name: "x" }, ctx);
// <w:my val="x"/>

当可选元素应被省略时返回 undefined

parse()

将 XML Element 解析为 Options 对象:

import { parse } from "@office-open/core";

const opts = parse(myDesc, element, ctx);

上下文

WriteContext

序列化过程中传递的上下文对象:

interface WriteContext {
  addRelationship(type: string, target: string, mode?: string): string;
  addMedia(data: Uint8Array, type: string): string;
}

ReadContext

解析过程中传递的上下文对象:

interface ReadContext {
  resolveRelationship(rId: string): string | undefined;
  getPart(path: string): XmlElement | undefined;
  getRaw(path: string): Uint8Array | undefined;
}

双向一致性

同一个描述符同时驱动序列化和解析,无需中间表示:

// 序列化
const xml = stringify(myDesc, { bold: true, size: 24 }, ctx);

// 解析
const parsed = parse(myDesc, element, ctx);

序列化过程直接生成 XML 字符串,不创建中间对象树,以减少内存分配。

何时直接使用

通常不需要直接调用 stringify()parse()。各格式包的顶层函数会自动处理:

  • generateDocument() / generatePresentation() / generateWorkbook() — 内部调用 stringify
  • parseDocument() / parsePresentation() / parseWorkbook() — 内部调用 parse

在以下场景直接使用描述符运行时:

  • 构建自定义 OOXML 部件的描述符
  • 调试序列化/解析结果
  • 实现格式包的部件模块

XSD 值映射

当 XSD 类型使用缩写时(例如 ST_TextAlignType"ctr" 表示 center),双向映射定义在 @office-open/coreutil/mappings.ts)中。每个映射通过 bidi() 一次性构建,提供 .to()(用户值 → XSD 值)和 .from()(XSD 值 → 用户值),同一个映射同时服务于序列化和解析:

import { xsdTextAlign } from "@office-open/core";

// 序列化(Options → XML)
attrs.push(`algn="${xsdTextAlign.to(options.alignment)}"`); // "center" → "ctr"

// 解析(XML → Options)
result.alignment = xsdTextAlign.from(String(el.attributes["algn"])); // "ctr" → "center"

当 XSD 已使用完整英文单词时(例如 "start""center"),无需映射——值直接原样写入和读取。

命名约定

约定示例
描述符名称:<part>DescspacingDescsettingsDescslideDesc
Options 接口:<Part>OptionsWorkbookOptionsDocumentOptions
辅助函数:stringify*() / parse*()stringifyWorksheet()parseWorkbook()
Copyright © 2026