# 结构验证

`OpenXmlValidator` 检查所选格式版本的结构与 SDK 支持的约束，不启动 Office，不检查分页、字体替换、渲染结果或 Excel 公式计算。

## 只读文件 → aardio 报告

这是可复制到测试代码中的局部函数，**不是本库新增的公共 API**。默认验证 DOCX；指定文档类后也适用于 XLSX / PPTX。

```aardio
import DocumentFormat.OpenXml;
var ox = DocumentFormat.OpenXml;

var validateFile = function(path,documentClass,fileFormat,maxErrors=100){
    documentClass := ox.Packaging.WordprocessingDocument;
    fileFormat := ox.FileFormatVersions.Office2007;
    var doc;

    var ok,result = call(function(){
        doc = documentClass.Open(path); // 默认只读
        var validator = ox.Validation.OpenXmlValidator(fileFormat);
        validator.MaxNumberOfErrors = maxErrors;
        var errors = [];

        // 创建验证结果和完整枚举均在错误边界内；枚举结束前不释放文档。
        for i,e in dotNet.each(validator.Validate(doc)) {
            var errorPath = e.Path;
            var errorPart = e.Part;
            table.push(errors,{
                id = e.Id;
                description = e.Description;
                part = errorPart ? tostring(errorPart.Uri) : null;
                xpath = errorPath ? errorPath.XPath : null;
            });
        }
        return {
            valid = !#errors;
            errors = errors;
            errorLimitReached = maxErrors > 0 && #errors >= maxErrors;
        };
    },null);

    var closed,closeError = true;
    if(doc) closed,closeError = call(function(){ doc.Dispose(); },null);
    if(!ok) return null,result;
    if(!closed) return null,closeError;
    return result;
};

return validateFile("/example.docx");
```

结果含义：

- 返回 `null, err`：打开、验证、枚举或关闭失败。**不是零错误验证通过。**
- `report.valid == false`：验证执行完成，但发现所选版本的结构错误。
- `report.valid == true`：验证执行完成且未发现该验证器覆盖的错误。
- `errorLimitReached` 只表示已达到上限，不表示精确知道剩余错误数。某些错误没有部件或 XPath，相应字段可缺省。

要验证 XLSX，将末行换为 `return validateFile("/example.xlsx", ox.Packaging.SpreadsheetDocument);`；PPTX 对应 `ox.Packaging.PresentationDocument`。应按实际文件种类选择文档类，不能仅改扩展名。

## 版本与上限

`OpenXmlValidator()` 默认目标是 **Office2007**，不是“当前最高格式版本”，也不依据文档自动选择。需要更高版本时显式传入单个 `FileFormatVersions` 值，例如 `ox.FileFormatVersions.Office2019`。SDK 版本和文档格式版本是两回事。

原生 `MaxNumberOfErrors` 默认 1000，0 表示不设上限；示例主动限制为 100。面向外部文件时宜设置上限；该上限不是文档体积或执行时长限制。

`Validate` 也可接受已打开的部件或 DOM 元素，但局部验证不能替代整个文档包的验证。SDK 结果应在文档释放前枚举完毕，并转为 aardio 字符串、数值或表后再跨线程传递。

## 用于生成器测试

分别断言：保存/打开成功、已知文本或数据一致、结构校验通过。另加一个故意放错位置的元素（例如把 `Wordprocessing.TableRow` 直接放入 `Body`）作为负例，确认验证器确实工作。

只读测试宜对比验证前后的文件字节，并在验证后尝试独占打开文件，检查是否遗留句柄。文档视觉验收是另一层测试，不应混入“结构通过”的结论。

原生签名与版本差异查 [OpenXmlValidator](https://learn.microsoft.com/dotnet/api/documentformat.openxml.validation.openxmlvalidator)。
