diff --git a/ofdgo_editor_versions.go b/ofdgo_editor_versions.go index 5272783..a3eddb5 100644 --- a/ofdgo_editor_versions.go +++ b/ofdgo_editor_versions.go @@ -345,13 +345,13 @@ func (r *Reader) versionSnapshotFiles(ctx context.Context) (map[string]bool, err if err != nil { return nil, err } - graph, err := r.versionEditGraph(ctx, entry, nil) + files, err := r.versionFileDependencies(ctx, entry, nil) if err != nil { return nil, err } if r.versionInfo != nil { for _, file := range r.versionInfo.Files { - graph.used[file.Location] = true + files[file.Location] = true } } body := r.OFD.DocBody[r.documentIndex] @@ -369,22 +369,22 @@ func (r *Reader) versionSnapshotFiles(ctx context.Context) (map[string]bool, err if err != nil { return nil, err } - graph.used[name] = true + files[name] = true } } if signature := r.versionSignatures(body.Signatures); signature != "" { - files, err := r.versionEditGraph(ctx, cleanPackagePath(signature), nil) + signed, err := r.versionFileDependencies(ctx, cleanPackagePath(signature), nil) if err != nil { return nil, err } - maps.Copy(graph.used, files.used) + maps.Copy(files, signed) } - for name := range graph.used { + for name := range files { if !r.fileNames[name] { return nil, fmt.Errorf("version file not found: %s", name) } } - return graph.used, ctx.Err() + return files, ctx.Err() } // retireVersionFiles 清理修改入口后不再被任何文档或版本引用的候选文件 diff --git a/ofdgo_reader_dependencies.go b/ofdgo_reader_dependencies.go index b72467e..d5d58a1 100644 --- a/ofdgo_reader_dependencies.go +++ b/ofdgo_reader_dependencies.go @@ -200,7 +200,7 @@ func (r *Reader) documentDependencies(ctx context.Context, index int) (map[strin if !r.fileNames[actual] { continue } - if err := r.documentFileReferences(ctx, actual, add); err != nil { + if err := r.documentFileReferences(ctx, actual, true, add); err != nil { return nil, nil, err } } @@ -208,9 +208,9 @@ func (r *Reader) documentDependencies(ctx context.Context, index int) (map[strin } // documentFileReferences 流式扫描结构文件,支持同一作用域内的未知命名空间 -// 入参: ctx 取消上下文, name 文件路径, add 接收引用路径及类别 +// 入参: ctx 取消上下文, name 文件路径, rejectUnknown 是否拒绝无法识别的扩展节点, add 接收引用路径及类别 // 返回: error 读取或结构错误 -func (r *Reader) documentFileReferences(ctx context.Context, name string, add func(string, int)) error { +func (r *Reader) documentFileReferences(ctx context.Context, name string, rejectUnknown bool, add func(string, int)) error { input, err := r.openFile(name) if err != nil { return err @@ -246,7 +246,13 @@ func (r *Reader) documentFileReferences(ctx context.Context, name string, add fu owner := stack[len(stack)-1] parent = owner.Local if classifyOFDNamespace(node.Name.Space) == ofdXMLUnknown && node.Name.Space != owner.Space { - return fmt.Errorf("cannot determine document dependencies in %s", name) + if rejectUnknown { + return fmt.Errorf("cannot determine document dependencies in %s", name) + } + if err := decoder.Skip(); err != nil { + return err + } + continue } } if parent == "Extension" && node.Name.Local == "Data" { diff --git a/ofdgo_version_edit.go b/ofdgo_version_edit.go index 7b43c71..8b5c706 100644 --- a/ofdgo_version_edit.go +++ b/ofdgo_version_edit.go @@ -44,6 +44,41 @@ type versionEditGraph struct { used map[string]bool } +// versionFileDependencies 流式汇总版本入口的标准文件引用,不保留页面节点或读取二进制资源 +// 入参: ctx 取消上下文, entry 文档入口, parts 待修改条目 +// 返回: map[string]bool 引用路径, error 读取、结构或取消错误 +func (r *Reader) versionFileDependencies(ctx context.Context, entry string, parts map[string][]byte) (map[string]bool, error) { + view := *r + if len(parts) != 0 { + view.files = maps.Clone(r.files) + if view.files == nil { + view.files = make(map[string][]byte, len(parts)) + } + maps.Copy(view.files, parts) + } + used := map[string]bool{entry: true} + queued := map[string]bool{entry: true} + queue := []string{entry} + add := func(name string, kind int) { + used[name] = true + if kind == packageReferenceXML && !queued[name] { + queued[name] = true + queue = append(queue, name) + } + } + for len(queue) != 0 { + if err := ctx.Err(); err != nil { + return nil, err + } + name := queue[0] + queue = queue[1:] + if err := view.documentFileReferences(ctx, name, false, add); err != nil { + return nil, err + } + } + return used, ctx.Err() +} + // versionEditGraph 沿标准文件引用建立版本依赖图,二进制资源只记录路径 // 入参: ctx 取消上下文, entry 文档入口, parts 待修改条目 // 返回: *versionEditGraph 依赖图, error 读取或结构错误 @@ -171,11 +206,11 @@ func (r *Reader) versionSharedFiles(ctx context.Context) (map[string]bool, error if err != nil { return nil, err } - graph, err := r.versionEditGraph(ctx, entry, nil) + files, err := r.versionFileDependencies(ctx, entry, nil) if err != nil { return nil, err } - maps.Copy(shared, graph.used) + maps.Copy(shared, files) } return shared, nil } @@ -191,26 +226,26 @@ func (r *Reader) versionResourceFiles(ctx context.Context, parts map[string][]by if err != nil { return nil, err } - graph, err := r.versionEditGraph(ctx, entry, parts) + files, err := r.versionFileDependencies(ctx, entry, parts) if err != nil { return nil, err } if r.versionInfo != nil { for _, file := range r.versionInfo.Files { - graph.used[file.Location] = true + files[file.Location] = true } } for index := range r.DocumentCount() { if index == r.documentIndex { continue } - files, err := r.documentFiles(ctx, index) + other, err := r.documentFiles(ctx, index) if err != nil { return nil, err } - maps.Copy(graph.used, files) + maps.Copy(files, other) } - return graph.used, nil + return files, nil } // versionChanges 隔离当前入口修改涉及的共享文件,同步版本清单,不修改输入包或修改集