S1000D数据模块与DMC编码:CSDB、BREX校验及IETM发布实践
2026/9/17 11:01:37 网站建设 项目流程

简介:这份资源是面向IETM从业者、装备保障与军工信息化技术人员的S1000D标准入门级PPT讲解材料,可用于快速建立对国际技术出版物标准的整体认知,适合零基础或需系统梳理知识框架的学习者。压缩包内仅含1个pptx文件,约697KB,采用幻灯片形式组织,便于按章节顺序阅读与直接引用。内容覆盖标准的发展历程与版本演进(1.00至4.01)、由欧洲ASD与美国AIA、ATA共同维护的组织格局,以及标准介绍、文档编制步骤、信息生成、信息管理、信息集和出版物、信息展现和使用、信息处理、术语和数据字典等编排结构章节。重点展开数据模块DM的原子性、DMID与STATUS等组成,以及公共源数据库CSDB的设计目的与实施流程。同时客观对比了降低维护费用、子集生成、异构系统交换、支持XML与WEB交互式电子技术手册等优点,并指出版本兼容、编码体制检索理解困难、国内欧标IETM应用尚不成熟等限制。目前已有1621人学习。

1. S1000D 不是排版手册:IETM 项目为什么卡在数据模块上

很多人第一次翻 S1000D 的资料,会把它当成一套文档模板:封面排好、章节分好、图贴上,剩下的交给编辑。真上项目,第一个卡点却是同一个问题——手册内容被拆成一个个数据模块后,谁负责哪一块、编号怎么给、两个承包商写的模块怎么保证不撞车。S1000D 解决的从来不是排版,而是内容以什么粒度存在、按什么规则检索、又能怎样被重新组装发布。它自 1989 年发布 1.0 起,经 2.x、3.0 走到 4.x,由欧洲 ASD 与美国 AIA、ATA 共同维护,版本之间的数据结构并不完全兼容。这份资料适合当地图用:先弄清 DM、CSDB、SNS 三个词指什么,再决定自己的项目上到哪一层。

2. 数据模块 DM 与公共源数据库 CSDB:S1000D 的存储模型

2.1 原子性决定协作边界

DM 最硬的一条约束是原子性:一个数据模块只描述装备的一个可维护单元,不可再拆,也不能跨两个维护级别。判断标准很朴素——把它整体拿出去,别的手册能不能直接复用?能,就说明粒度对了。例如"更换制动片"是一个程序类 DM,"制动片零件清单"是一个 IPD 类 DM,"制动系统概述"是一个描述类 DM,三者不会混在一个文件里。

反过来,如果一个 DM 里出现了"仅 A 机型执行第 3 步"这种句子,问题通常不在粒度,而在适用性(applicability)没定义好。原子性还决定了协作方式:DM 是分工的最小单位,谁写哪个 DMC,在业务规则阶段就要定死,否则后期合并 CSDB 时会出现大量重复内容。

2.2 CSDB 里到底存了哪些对象

CSDB 是 S1000D 里的中央仓库,产品全部技术信息都放这里,但它不是"一个文件夹",而是一组受控对象。常见的几类对象如下。

对象类型文件名常见前缀作用
数据模块 DMDMC-内容主体,含描述、程序、IPD、故障隔离等
出版物模块 PMPMC-把若干 DM 按顺序组装成一本书
数据模块清单 DMLDML-成批引用 DM,用于中大型项目
业务规则交换 BREXDMC-(特定信息码)项目自定义的结构与写作约束
适用性交叉引用表 ACTACT-产品属性值与适用性数据
图形与多媒体 ICNICN-CGM、SVG、光栅图等插图对象

文件名一般由 DM 代码、版本号、语言三段组成,例如DMC-S1000DBIKE-AAA-D00-0-0-00-00A-A-041-A-A_0001-00_zh-CN.XML,其中0001是版本号,00表示已发布状态,zh-CN是语言标识。实践中把 DMC 和文件名保持严格一致收益很高——脚本可以只靠文件名建索引,不必解析全部 XML。

2.3 DM 的四段结构

一个 DM 在逻辑上分成几块,缺一块都会导致下游工具解析失败。identAndStatusSection里放dmAddress(含dmIdentlanguageissueInfo、标题)和dmStatus(密级、责任单位、原始单位、适用性、BREX 引用、QA 状态)。content才是人看到的内容,按类型分成描述性、程序性、IPD、故障、维修计划、接线等几种。

注意:dmStatus中的brexDmRef不是可选项。缺了它,校验工具无法知道该用哪套业务规则来检查这个 DM。

理解这个分层的价值在于:检索、权限过滤、版本控制全部作用在前两段,转换样式表只关心content。曾经为了加一条"仅限某批次"的限制去改正文,其实只要动dmStatus里的适用性表达式。

2.4 一个最小 DM 的 XML 骨架

下面是一个近似 4.x 结构的最小 DM,字段长度和元素名以项目所用 issue 的 DTD 为准,这里只保留能跑通校验的骨架。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dmodule SYSTEM "./dtd/dmodule.dtd"> <dmodule> <identAndStatusSection> <dmAddress> <dmIdent> <!-- 11 个属性拼出完整 DMC,顺序不能乱 --> <dmCode modelIdentCode="S1000DBIKE" systemDiffCode="AAA" systemCode="D00" subSystemCode="0" subSubSystemCode="0" assyCode="00" disassyCode="00" disassyCodeVariant="A" infoCode="041" infoCodeVariant="A" itemLocationCode="A"/> <language languageIsoCode="zh" countryIsoCode="CN"/> <issueInfo issueNumber="0001" inWork="00"/> </dmIdent> <dmAddressItems> <issueDate year="2024" month="03" day="12"/> <dmTitle> <techName>制动系统概述</techName> <infoName>说明</infoName> </dmTitle> </dmAddressItems> </dmAddress> <dmStatus> <security securityClassification="01"/> <responsiblePartnerCompany> <enterpriseName>示例公司</enterpriseName> </responsiblePartnerCompany> <originator> <enterpriseName>示例公司</enterpriseName> </originator> <applic> <displayText><simplePara>全部机型</simplePara></displayText> </applic> <!-- 指向本项目的 BREX 模块,校验时按它挑规则 --> <brexDmRef> <dmRef> <dmRefIdent> <dmCode modelIdentCode="S1000DBIKE" systemDiffCode="AAA" systemCode="D00" subSystemCode="0" subSubSystemCode="0" assyCode="00" disassyCode="00" disassyCodeVariant="A" infoCode="022" infoCodeVariant="A" itemLocationCode="A"/> </dmRefIdent> </dmRef> </brexDmRef> <qaStatus><qaStatusType>02</qaStatusType></qaStatus> </dmStatus> </identAndStatusSection> <content> <description> <para>本模块概述制动系统的组成与工作原理。</para> </description> </content> </dmodule>

关键点有三个:dmCode的属性顺序与取值直接决定这个文件在 CSDB 中的身份,写错一位就是另一个模块;issueInfoissueNumber在各版本中补零位数不同,迁移时最先出问题的就是它;brexDmRef里填的是项目自己的 BREX 模块,不是标准的某个固定值。

3. DMC 编码体系:SNS、信息码与学习码怎么定

3.1 DMC 的组成字段

数据模块代码是 S1000D 里检索能力的来源,它把"哪台设备、哪个系统、什么内容、装在哪"压缩进一串字符。按 4.x 的顺序,大致分成 11 段。

顺序字段含义示例
1modelIdentCode型号标识S1000DBIKE
2systemDiffCode系统差异码AAA
3systemCode系统码(常沿用 ATA 章节)D00
4subSystemCode子系统码0
5subSubSystemCode子子系统码0
6assyCode装配件码00
7disassyCode拆解码00
8disassyCodeVariant拆解码变体A
9infoCode信息码041
10infoCodeVariant信息码变体A
11itemLocationCode位置码A

前八段构成定位,后三段描述内容。民用航空项目里systemCode多数直接沿用 ATA 章节号,机务看到 32、29 就能猜到起落架和液压;军用车船项目通常自建 SNS。混用是最大的坑:同一份 CSDB 里一半按 ATA、一半按自建体系,检索会彻底失效。

3.2 SNS 与信息码的分配策略

SNS 是标准编号系统,管的是"东西在哪";信息码管的是"讲什么"。信息码按类型分组,粗粒度上可以这样理解:0xx 偏功能与描述,1xx 到 2xx 偏程序与故障隔离,3xx 到 6xx 偏维修与修理,9xx 是 IPD 类零件数据。具体到每一段怎么切,各 issue 略有差异,不要凭记忆写,直接从所用版本的 info code 清单里查。

分配策略上,我一般坚持三条:信息码只从官方清单里挑,项目自定义的一律不进infoCode;一个信息码只对应一种content结构,写完在业务规则里登记;变体位(variant)只在同信息码下确有内容差异时启用,不要拿它当版本号用。第三条最容易被破坏,变体位一旦被当版本号,DM 数量会成倍膨胀。

3.3 学习码与培训场景

学习码(Learning Code,简称 LC)用在培训类数据模块上,和信息码组合,标出培训对象和培训层级——操作级、维护级、修理级各有不同标记。它出现的前提是项目本身有培训体系,否则启用后只会增加编码负担。判断方法很直接:如果培训内容和技术手册内容是同一批人写、同一套评审流程,就先上学习码;如果是独立团队,等培训材料真正并进 CSDB 再说。

提示:学习码与适用性经常被混为一谈。前者描述"这份内容给谁学",后者描述"这份内容适用于哪个产品"。写反了,IETP 里会出现给操作工看的修理程序。

3.4 用脚本批量拆 DMC 做统计

一旦 DM 超过几百个,靠人眼核对编码体系是不现实的。下面这段脚本把 CSDB 里所有 DMC 拆开做分布统计,能快速看出编号体系是否统一。

from pathlib import Path import xml.etree.ElementTree as ET from collections import Counter CSDB = Path("./csdb") ATTRS = ["modelIdentCode", "systemDiffCode", "systemCode", "subSystemCode", "subSubSystemCode", "assyCode", "disassyCode", "disassyCodeVariant", "infoCode", "infoCodeVariant", "itemLocationCode"] def dmc_parts(el): # 用 "-" 拼回完整 DMC,缺属性会暴露成空字符串 return {a: (el.get(a) or "") for a in ATTRS} system_counter = Counter() info_counter = Counter() broken = [] for f in CSDB.glob("DMC-*.XML"): el = ET.parse(f).getroot().find(".//dmCode") if el is None: broken.append((f.name, "找不到 dmCode")) continue parts = dmc_parts(el) if any(v == "" for v in parts.values()): broken.append((f.name, "DMC 字段缺失")) continue system_counter[parts["systemCode"]] += 1 info_counter[parts["infoCode"][:1]] += 1 # 按信息码首位分组 print("系统码分布:", system_counter.most_common()) print("信息码大类分布:", info_counter.most_common()) print("异常文件:", broken)

脚本的逻辑是先用.//dmCode抓到模块身份节点,再把 11 个属性收成字典,任一为空就判定为编码不完整;随后按systemCode和信息码首位做频次统计。infoCode[:1]取首位是有意为之——首位就能区分描述类、程序类、维修类和 IPD 类,比看完整三位更快发现"同一系统下塞了不该有的内容类型"。异常清单必须清零,否则后面组包时会出现莫名其妙的缺页。

4. XML 校验与 BREX 业务规则:让 CSDB 能自动挑错

4.1 DTD/XSD 放在哪、DOCTYPE 怎么写

S1000D 的 DM 文件用 SGML 或 XML 组织,靠 DTD 或 Schema 约束标记。工程上最常见的失败不是内容写错,而是路径写错:验证时用的是绝对路径,换台机器或换个目录就全红。稳妥做法是把 DTD/Schema 一起入库,目录结构固定,DOCTYPE里写相对路径。

project/ ├─ csdb/ # 所有 DM、PM、BREX、ACT 文件 ├─ dtd/ # 官方 DTD,随项目入库,不依赖本地环境 ├─ schema/ # 官方 XSD,用于需要命名空间校验的场景 ├─ xsl/ # 转换样式表 └─ build/ # 输出产物,不进版本库

注意:DTD 文件和 CSDB 一起纳入版本控制,是后续能做可重复构建的前提。只把 DTD 装在个人机器上,等于把校验能力绑死在某个人的环境里。

4.2 xmllint 批量校验与报错定位

xmllint是排查结构问题最快的工具,先单文件验证,再批量跑。

# 单文件按 DTD 校验,--noout 表示不输出 XML 内容 xmllint --noout --valid csdb/DMC-S1000DBIKE-AAA-D00-0-0-00-00A-A-041-A-A_0001-00_zh-CN.XML # 按 XSD 校验,适合 Schema 里带类型约束的场景 xmllint --noout --schema ./schema/dmodule.xsd csdb/*.XML # 批量跑,只保留报错行,方便接进 CI find csdb -name '*.XML' -print0 \ | xargs -0 -n1 xmllint --noout --valid 2>&1 \ | grep -iE 'error|warning' | sort -u

参数上,--valid触发 DTD 校验,--schema走 XSD,两者不要同时用在同一批文件上,否则报错信息会互相淹没。批量时用-print0 | xargs -0是为了兼容文件名里的特殊字符;-n1保证一次只处理一个文件,出错时能直接定位到文件名。常见报错有两类:Content model of X is incomplete多半是漏了必填子元素,通常是dmStatus里的责任单位或 QA 状态;No declaration for element则是版本搞混了,用 4.x 的 DTD 去校验 2.2 结构的文件必然报这个。

4.3 BREX 与 Schematron 的分工

BREX 是项目写在 CSDB 里的业务规则模块,用来约束"我们这个项目允许怎么写",比如标题必填、只能用某几种信息码、图形必须同时提供替代文本。它的价值是把口头约定变成机器可校验的规则。实际项目中 BREX 的解析工具链不总是齐全,所以常见做法是双层校验:BREX 作为规则台账放进 CSDB,具体执行用 Schematron 落地,两者保持一一对应。

<schema xmlns="http://purl.oclc.org/dsdl/schematron"> <pattern> <rule context="dmCode"> <!-- 信息码必须三位,且只允许项目已登记的大类 --> <assert test="string-length(@infoCode) = 3">信息码必须为三位</assert> <assert test="starts-with(@infoCode, '0') or starts-with(@infoCode, '1') or starts-with(@infoCode, '9')"> 本项目只允许描述类、程序类与 IPD 类信息码 </assert> <assert test="@itemLocationCode = 'A'"> 现阶段只允许整机位置码 A </assert> </rule> <rule context="dmTitle"> <assert test="normalize-space(techName) != ''">techName 不允许为空</assert> </rule> </pattern> </schema>

context决定规则作用在哪个元素上,assert里的 XPath 写出不满足的条件描述。规则数量不要一上来就堆到几十条,先挑最容易出错的几条跑通,再加入编码类、图形引用类规则。规则文本要能被人读懂——校验失败的提示是给作者看的,不是给工具看的。

4.4 ACT 适用性过滤

适用性数据集中在 ACT 对象里,DM 通过引用属性值声明"我适用于谁"。过滤的实质是集合运算:把 ACT 里的产品属性值与 DM 的适用性表达式求交,得到每个具体产品该看到哪些模块。表达式里用andornot组合断言,属性名必须来自业务规则里定义的产品属性字典。

提示:不要用适用性替代版本管理。同一条内容改了一句话,应该升版本号;只有确实面向不同配置时才用适用性。

5. 从 CSDB 到 IETP:PM 组包、XSLT 转换与发布链路

5.1 PM 怎么引用 DM

出版物模块只做一件事:按顺序引用 DM,并声明适用范围。它本身不含正文,所以修订内容时改 DM 即可,PM 不用动。

<pm> <identAndStatusSection> <!-- PM 的身份与状态,结构与 DM 类似,含 pmCode、标题与密级 --> </identAndStatusSection> <content> <pmEntry> <dmRef> <dmRefIdent> <dmCode modelIdentCode="S1000DBIKE" systemDiffCode="AAA" systemCode="D00" subSystemCode="0" subSubSystemCode="0" assyCode="00" disassyCode="00" disassyCodeVariant="A" infoCode="041" infoCodeVariant="A" itemLocationCode="A"/> </dmRefIdent> <dmRefAddressItems> <dmTitle><techName>制动系统概述</techName> <infoName>说明</infoName></dmTitle> </dmRefAddressItems> </dmRef> </pmEntry> <!-- 后续 pmEntry 按阅读顺序继续追加 --> </content> </pm>

引用时要写全 DMC,不要只写文件名。文件名会随版本和语言变化,DMC 是稳定的。PM 引用完一定要做悬空检查,引了不存在的 DM,转换阶段只会输出一个空洞,不会报错。

5.2 XSLT 到 PDF 和 HTML 的两条输出线

同一份 CSDB 通常要出两种产物:面向页的 PDF 和面向交互的 IETP。两者共用同一套 XSLT 前置处理,区别在后端。

# 线一:出面向页 PDF,先转 XSL-FO 再渲染 xsltproc --stringparam lang zh-CN ./xsl/pm2fo.xsl csdb/PMC-BIKE-00001-00_zh-CN.XML > build/pm.fo fop -fo build/pm.fo -pdf build/manual.pdf # 线二:出 HTML 片段,供 IETP 前端组装 xsltproc --stringparam lang zh-CN ./xsl/pm2html.xsl csdb/PMC-BIKE-00001-00_zh-CN.XML > build/pm.html

--stringparam lang用来切换输出语言,多语言 CSDB 靠它选对应语言的 DM。IETP 侧常见的实现是静态资源加一层检索索引:把每个 DM 转成独立 HTML 片段,再生成一份以 DMC 为键的索引,前端按需加载,图形走 ICN 对象引用。

5.3 CSDB 一致性体检脚本

发布前跑一遍一致性检查,比出问题后翻日志划算得多。

from pathlib import Path import xml.etree.ElementTree as ET CSDB = Path("./csdb") ATTRS = ["modelIdentCode", "systemDiffCode", "systemCode", "subSystemCode", "subSubSystemCode", "assyCode", "disassyCode", "disassyCodeVariant", "infoCode", "infoCodeVariant", "itemLocationCode"] def key_of(el): return "-".join(el.get(a, "") for a in ATTRS) dm_index = {} for f in CSDB.glob("DMC-*.XML"): root = ET.parse(f).getroot() code = root.find(".//dmIdent/dmCode") # 只取身份段,避免抓到正文里的引用 dm_index.setdefault(key_of(code), []).append(f.name) for dmc, files in dm_index.items(): if len(files) > 1: print("[重复 DMC]", dmc, files) for f in CSDB.glob("PM*.XML"): root = ET.parse(f).getroot() for ref in root.iter("dmRefIdent"): dmc = key_of(ref.find("dmCode")) if dmc not in dm_index: print("[悬空引用]", f.name, "->", dmc)

这段脚本和 3.4 的版本有两个关键差别。一是取dmCode时用了.//dmIdent/dmCode而不是.//dmCode,因为 DM 文件内部还有其他引用节点,通配会抓错;二是多了一步引用完整性检查,把 PM 里出现的 DMC 与索引比对。输出为空才算通过,重复 DMC 意味着两个作者写了同一个模块,必须人工裁决保留哪一份。

5.4 版本迁移与几个反复踩的坑

现象常见原因处理方式
换机器后校验全红DTD 路径写成绝对路径DTD 目录随项目入库,DOCTYPE 用相对路径
中文变乱码文件声明与保存编码不一致统一 UTF-8,转换脚本显式声明输出编码
IETP 里图不显示ICN 对象未随 CSDB 一起发布把图形目录纳入发布清单并做引用检查
迁移后结构报错跨 issue 迁移,元素名与位数变化先做结构映射表,再批量改写,逐版本验证
手册越来越厚适用性缺失,所有配置都被塞进同一本补 ACT 数据,用适用性过滤而非删内容

迁移是 S1000D 项目里最耗人的环节。版本更新快且不完全兼容,所以每次迁移都应该先做一份映射表:源元素、目标元素、转换规则、是否丢失信息。转换脚本跑完必须重新过一遍 DTD 校验和 BREX 校验,两者都通过才算迁移完成。

6. 把 S1000D 用轻:小项目的裁剪做法与验证清单

不是所有项目都需要完整落地 S1000D 的九个章节。DM、CSDB、SNS 概念更适配多承包商、大型多系统项目;单机、单团队的小项目硬套全套,开发周期会明显拉长。我一般建议按三层裁剪:第一层只做 DM 与 PM,把所有内容拆成原子模块并组包;第二层加 DTD 校验和一套精简 BREX;第三层再加 ACT 适用性、学习码和多语言。三层按需推进,任何一层都不影响后续向上兼容。

裁剪时保留余地比省事更重要。SNS 即使自建,也建议在systemCode上留出与主流章节号对齐的映射表;信息码即使只用几种,也坚持从官方清单里挑;dmStatus里的字段即便暂时填默认值,也不要删元素。删了以后想补回来,等于全部 DM 重写一遍。

配套的验证清单建议直接落成脚本,每次提交前跑一遍:

检查项通过标准
DTD 或 XSD 校验零错误,警告需逐条确认
BREX/Schematron 规则规则数与业务规则台账一致,全部通过
DMC 唯一性无重复,无字段缺失
PM 引用完整性无悬空引用,无未引用的孤立 DM
图形引用每个 ICN 引用都能在发布清单里找到实体文件
语言一致性文件名语言标识与language元素一致

一个提高规则命中率的技巧:BREX 或 Schematron 的第一版只写八到十条规则,锁定最容易出错的四类问题——必填元素缺失、信息码越界、标题为空、引用悬空。跑两周统计触发次数,把从不触发的规则删掉,把频繁触发的规则补上更明确的提示文案,再逐步扩展到编码格式和图形规范。规则数量增长太快,作者会养成"绕过校验"的习惯,那套校验就白做了。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询