mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 14:31:12 +08:00
1 parent
2e3809179b
commit
d7e9604282
4 files changed
+137
-43
No files matched your search
+99
-18
@@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -91,17 +92,28 @@ func (r *Reader) DocumentIndex() int {
|
|||||||
// 入参: index 文档索引,从0开始
|
// 入参: index 文档索引,从0开始
|
||||||
// 返回: int 页数, error 错误信息
|
// 返回: int 页数, error 错误信息
|
||||||
func (r *Reader) DocumentPageCount(index int) (int, error) {
|
func (r *Reader) DocumentPageCount(index int) (int, error) {
|
||||||
|
return r.DocumentPageCountContext(context.Background(), index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocumentPageCountContext 获取指定文档页数,读取和解析时响应取消,不加载关联资源
|
||||||
|
// 入参: ctx 取消上下文, index 文档索引,从0开始
|
||||||
|
// 返回: int 页数, error 选择、读取或取消错误
|
||||||
|
func (r *Reader) DocumentPageCountContext(ctx context.Context, index int) (int, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
if index < 0 || index >= r.DocumentCount() {
|
if index < 0 || index >= r.DocumentCount() {
|
||||||
return 0, fmt.Errorf("document index %d out of range", index)
|
return 0, fmt.Errorf("document index %d out of range", index)
|
||||||
}
|
}
|
||||||
if index == r.documentIndex && r.doc != nil {
|
if index == r.documentIndex && r.doc != nil {
|
||||||
return len(r.doc.Pages.Page), nil
|
return len(r.doc.Pages.Page), nil
|
||||||
}
|
}
|
||||||
root, err := r.documentEntry(index)
|
view := *r
|
||||||
|
root, err := view.documentEntryContext(ctx, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
data, err := r.readFile(root)
|
data, err := r.readFileViewContext(ctx, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -109,9 +121,16 @@ func (r *Reader) DocumentPageCount(index int) (int, error) {
|
|||||||
XMLName xml.Name `xml:"Document"`
|
XMLName xml.Name `xml:"Document"`
|
||||||
Pages Pages `xml:"Pages"`
|
Pages Pages `xml:"Pages"`
|
||||||
}
|
}
|
||||||
if err := xml.Unmarshal(data, &doc); err != nil {
|
decoder := xml.NewDecoder(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), context: ctx})
|
||||||
|
if err := decoder.Decode(&doc); err != nil {
|
||||||
return 0, fmt.Errorf("failed to unmarshal document.xml: %w", err)
|
return 0, fmt.Errorf("failed to unmarshal document.xml: %w", err)
|
||||||
}
|
}
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if index == r.documentIndex {
|
||||||
|
r.documentRoot, r.versionInfo = view.documentRoot, view.versionInfo
|
||||||
|
}
|
||||||
return len(doc.Pages.Page), nil
|
return len(doc.Pages.Page), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +170,16 @@ func (r *Reader) Doc() (*Document, error) {
|
|||||||
// docStructure 读取文档及资源索引,关联注解和签名由Doc按需解析
|
// docStructure 读取文档及资源索引,关联注解和签名由Doc按需解析
|
||||||
// 返回: *Document 文档结构, error 错误信息
|
// 返回: *Document 文档结构, error 错误信息
|
||||||
func (r *Reader) docStructure() (*Document, error) {
|
func (r *Reader) docStructure() (*Document, error) {
|
||||||
|
return r.docStructureContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// docStructureContext 读取文档及资源索引,取消或失败时保留原阅读状态
|
||||||
|
// 入参: ctx 取消上下文
|
||||||
|
// 返回: *Document 文档结构, error 读取、解析或取消错误
|
||||||
|
func (r *Reader) docStructureContext(ctx context.Context) (*Document, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if r.doc != nil {
|
if r.doc != nil {
|
||||||
return r.doc, nil
|
return r.doc, nil
|
||||||
}
|
}
|
||||||
@@ -158,30 +187,55 @@ func (r *Reader) docStructure() (*Document, error) {
|
|||||||
return nil, fmt.Errorf("no docbody found")
|
return nil, fmt.Errorf("no docbody found")
|
||||||
}
|
}
|
||||||
docAttr := r.OFD.DocBody[r.documentIndex]
|
docAttr := r.OFD.DocBody[r.documentIndex]
|
||||||
docRootPath, err := r.DocumentRoot()
|
view := *r
|
||||||
|
docRootPath, err := view.DocumentRootContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.RootDir = path.Dir(docRootPath)
|
view.RootDir = path.Dir(docRootPath)
|
||||||
data, err := r.readFile(docRootPath)
|
data, err := view.readFileViewContext(ctx, docRootPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var doc Document
|
var doc Document
|
||||||
if err := xml.Unmarshal(data, &doc); err != nil {
|
decoder := xml.NewDecoder(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), context: ctx})
|
||||||
|
if err := decoder.Decode(&doc); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal document.xml: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal document.xml: %w", err)
|
||||||
}
|
}
|
||||||
if doc.Signatures == "" {
|
if doc.Signatures == "" {
|
||||||
doc.Signatures = r.versionSignatures(docAttr.Signatures)
|
doc.Signatures = view.versionSignatures(docAttr.Signatures)
|
||||||
}
|
}
|
||||||
|
view.resourcesRead = maps.Clone(r.resourcesRead)
|
||||||
|
view.resourceFiles = maps.Clone(r.resourceFiles)
|
||||||
|
view.ResMap = maps.Clone(r.ResMap)
|
||||||
|
view.mediaCache = maps.Clone(r.mediaCache)
|
||||||
|
view.fontCache = maps.Clone(r.fontCache)
|
||||||
|
view.colorSpaceCache = maps.Clone(r.colorSpaceCache)
|
||||||
|
view.drawParamCache = maps.Clone(r.drawParamCache)
|
||||||
|
view.compositeGraphicUnitCache = maps.Clone(r.compositeGraphicUnitCache)
|
||||||
for _, res := range doc.CommonData.DocumentRes {
|
for _, res := range doc.CommonData.DocumentRes {
|
||||||
r.loadRes(res)
|
if err := view.loadResContext(ctx, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, res := range doc.CommonData.PublicRes {
|
for _, res := range doc.CommonData.PublicRes {
|
||||||
r.loadRes(res)
|
if err := view.loadResContext(ctx, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
r.doc = &doc
|
if err := ctx.Err(); err != nil {
|
||||||
r.relatedPending = true
|
return nil, err
|
||||||
|
}
|
||||||
|
maps.Copy(r.resourcesRead, view.resourcesRead)
|
||||||
|
maps.Copy(r.resourceFiles, view.resourceFiles)
|
||||||
|
maps.Copy(r.ResMap, view.ResMap)
|
||||||
|
maps.Copy(r.mediaCache, view.mediaCache)
|
||||||
|
maps.Copy(r.fontCache, view.fontCache)
|
||||||
|
maps.Copy(r.colorSpaceCache, view.colorSpaceCache)
|
||||||
|
maps.Copy(r.drawParamCache, view.drawParamCache)
|
||||||
|
maps.Copy(r.compositeGraphicUnitCache, view.compositeGraphicUnitCache)
|
||||||
|
r.documentRoot, r.versionInfo, r.RootDir = view.documentRoot, view.versionInfo, view.RootDir
|
||||||
|
r.doc, r.relatedPending = &doc, true
|
||||||
return r.doc, nil
|
return r.doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,23 +720,37 @@ func readZipFile(f *zip.File) ([]byte, error) {
|
|||||||
// loadRes 加载资源文件
|
// loadRes 加载资源文件
|
||||||
// 入参: resPath 资源路径
|
// 入参: resPath 资源路径
|
||||||
func (r *Reader) loadRes(resPath string) {
|
func (r *Reader) loadRes(resPath string) {
|
||||||
|
_ = r.loadResContext(context.Background(), resPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadResContext 加载可读资源的索引,读取、解析和遍历时响应取消
|
||||||
|
// 入参: ctx 取消上下文, resPath 资源路径
|
||||||
|
// 返回: error 取消错误
|
||||||
|
func (r *Reader) loadResContext(ctx context.Context, resPath string) error {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if resPath == "" {
|
if resPath == "" {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
fullPath := r.ResPath(resPath)
|
fullPath := r.ResPath(resPath)
|
||||||
if r.resourcesRead[fullPath] {
|
if r.resourcesRead[fullPath] {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
data, err := r.readFile(fullPath)
|
data, err := r.readFileViewContext(ctx, fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
var res Res
|
var res Res
|
||||||
if err := xml.Unmarshal(data, &res); err != nil {
|
decoder := xml.NewDecoder(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), context: ctx})
|
||||||
return
|
if err := decoder.Decode(&res); err != nil {
|
||||||
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
baseLoc := res.BaseLoc
|
baseLoc := res.BaseLoc
|
||||||
for i := range res.ColorSpaces.ColorSpace {
|
for i := range res.ColorSpaces.ColorSpace {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
cs := &res.ColorSpaces.ColorSpace[i]
|
cs := &res.ColorSpaces.ColorSpace[i]
|
||||||
if cs.Profile != "" {
|
if cs.Profile != "" {
|
||||||
cs.Profile = r.resourceLocation(fullPath, baseLoc, cs.Profile)
|
cs.Profile = r.resourceLocation(fullPath, baseLoc, cs.Profile)
|
||||||
@@ -691,6 +759,9 @@ func (r *Reader) loadRes(resPath string) {
|
|||||||
r.resourceFiles[cs.ID] = fullPath
|
r.resourceFiles[cs.ID] = fullPath
|
||||||
}
|
}
|
||||||
for _, mm := range res.MultiMedias.MultiMedia {
|
for _, mm := range res.MultiMedias.MultiMedia {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if mm.MediaFile != "" {
|
if mm.MediaFile != "" {
|
||||||
if finalPath := r.resourceLocation(fullPath, baseLoc, mm.MediaFile); finalPath != "" {
|
if finalPath := r.resourceLocation(fullPath, baseLoc, mm.MediaFile); finalPath != "" {
|
||||||
mm.MediaFile = finalPath
|
mm.MediaFile = finalPath
|
||||||
@@ -704,6 +775,9 @@ func (r *Reader) loadRes(resPath string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range res.Fonts.Font {
|
for i := range res.Fonts.Font {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
f := &res.Fonts.Font[i]
|
f := &res.Fonts.Font[i]
|
||||||
if f.FontFile != "" {
|
if f.FontFile != "" {
|
||||||
f.FontFile = r.resourceLocation(fullPath, baseLoc, f.FontFile)
|
f.FontFile = r.resourceLocation(fullPath, baseLoc, f.FontFile)
|
||||||
@@ -712,16 +786,23 @@ func (r *Reader) loadRes(resPath string) {
|
|||||||
r.resourceFiles[f.ID] = fullPath
|
r.resourceFiles[f.ID] = fullPath
|
||||||
}
|
}
|
||||||
for i := range res.DrawParams.DrawParam {
|
for i := range res.DrawParams.DrawParam {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
dp := &res.DrawParams.DrawParam[i]
|
dp := &res.DrawParams.DrawParam[i]
|
||||||
r.drawParamCache[dp.ID] = dp
|
r.drawParamCache[dp.ID] = dp
|
||||||
r.resourceFiles[dp.ID] = fullPath
|
r.resourceFiles[dp.ID] = fullPath
|
||||||
}
|
}
|
||||||
for i := range res.CompositeGraphicUnits.CompositeGraphicUnit {
|
for i := range res.CompositeGraphicUnits.CompositeGraphicUnit {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
cgu := &res.CompositeGraphicUnits.CompositeGraphicUnit[i]
|
cgu := &res.CompositeGraphicUnits.CompositeGraphicUnit[i]
|
||||||
r.compositeGraphicUnitCache[cgu.ID] = cgu
|
r.compositeGraphicUnitCache[cgu.ID] = cgu
|
||||||
r.resourceFiles[cgu.ID] = fullPath
|
r.resourceFiles[cgu.ID] = fullPath
|
||||||
}
|
}
|
||||||
r.resourcesRead[fullPath] = true
|
r.resourcesRead[fullPath] = true
|
||||||
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// resourceLocation 按资源XML所在位置解析文件,文档目录外的共享文件保留绝对路径
|
// resourceLocation 按资源XML所在位置解析文件,文档目录外的共享文件保留绝对路径
|
||||||
|
|||||||
@@ -166,13 +166,6 @@ func parseVersionEntries(ctx context.Context, body *editorXML) ([]DocumentVersio
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readDocumentVersion 读取版本描述,按描述文件位置解析文件清单和文档入口
|
|
||||||
// 入参: id 入口中的版本标识, location 描述文件路径
|
|
||||||
// 返回: DocumentVersionInfo 版本信息, error 读取或描述错误
|
|
||||||
func (r *Reader) readDocumentVersion(id, location string) (DocumentVersionInfo, error) {
|
|
||||||
return r.readDocumentVersionContext(context.Background(), id, location)
|
|
||||||
}
|
|
||||||
|
|
||||||
// readDocumentVersionContext 读取版本描述,按描述文件位置解析清单和文档入口
|
// readDocumentVersionContext 读取版本描述,按描述文件位置解析清单和文档入口
|
||||||
// 入参: ctx 取消上下文, id 入口中的版本标识, location 描述文件路径
|
// 入参: ctx 取消上下文, id 入口中的版本标识, location 描述文件路径
|
||||||
// 返回: DocumentVersionInfo 版本信息, error 读取、描述或取消错误
|
// 返回: DocumentVersionInfo 版本信息, error 读取、描述或取消错误
|
||||||
|
|||||||
+38
-11
@@ -16,6 +16,7 @@ package ofdgo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,12 +26,23 @@ import (
|
|||||||
// 入参: id 版本标识,空值选择唯一的Current版本,没有默认版本或存在歧义时返回错误
|
// 入参: id 版本标识,空值选择唯一的Current版本,没有默认版本或存在歧义时返回错误
|
||||||
// 返回: *Reader 版本阅读器, error 选择、读取或文件缺失错误
|
// 返回: *Reader 版本阅读器, error 选择、读取或文件缺失错误
|
||||||
func (r *Reader) ExtractVersion(id string) (*Reader, error) {
|
func (r *Reader) ExtractVersion(id string) (*Reader, error) {
|
||||||
entries, err := r.documentVersionEntries()
|
return r.ExtractVersionContext(context.Background(), id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractVersionContext 将指定版本提取为独立阅读器,扫描、读取和解析时响应取消
|
||||||
|
// 文件保留范围、入口选择和输入文件生命周期与ExtractVersion相同,取消或失败不改变原包
|
||||||
|
// 入参: ctx 取消上下文, id 版本标识,空值选择唯一的Current版本
|
||||||
|
// 返回: *Reader 版本阅读器, error 选择、读取或取消错误
|
||||||
|
func (r *Reader) ExtractVersionContext(ctx context.Context, id string) (*Reader, error) {
|
||||||
|
entries, err := r.documentVersionEntriesContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var selected *DocumentVersionInfo
|
var selected *DocumentVersionInfo
|
||||||
for i := range entries {
|
for i := range entries {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
entry := &entries[i]
|
entry := &entries[i]
|
||||||
if id != "" && entry.ID == id || id == "" && entry.Current {
|
if id != "" && entry.ID == id || id == "" && entry.Current {
|
||||||
if selected != nil {
|
if selected != nil {
|
||||||
@@ -45,23 +57,29 @@ func (r *Reader) ExtractVersion(id string) (*Reader, error) {
|
|||||||
}
|
}
|
||||||
return nil, fmt.Errorf("document version not found: %s", id)
|
return nil, fmt.Errorf("document version not found: %s", id)
|
||||||
}
|
}
|
||||||
version, err := r.readDocumentVersion(selected.ID, selected.Location)
|
version, err := r.readDocumentVersionContext(ctx, selected.ID, selected.Location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("version %s: %w", selected.ID, err)
|
return nil, fmt.Errorf("version %s: %w", selected.ID, err)
|
||||||
}
|
}
|
||||||
files := make(map[string]bool, len(version.Files))
|
files := make(map[string]bool, len(version.Files))
|
||||||
for _, file := range version.Files {
|
for _, file := range version.Files {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if !r.fileNames[file.Location] {
|
if !r.fileNames[file.Location] {
|
||||||
return nil, fmt.Errorf("version %s file not found: %s", selected.ID, file.Location)
|
return nil, fmt.Errorf("version %s file not found: %s", selected.ID, file.Location)
|
||||||
}
|
}
|
||||||
files[file.Location] = true
|
files[file.Location] = true
|
||||||
}
|
}
|
||||||
root, err := r.extractedVersionRoot(version, files)
|
root, err := r.extractedVersionRoot(ctx, version, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
next := &Reader{Path: r.Path, files: map[string][]byte{"OFD.xml": root}, encryption: r.encryption}
|
next := &Reader{Path: r.Path, files: map[string][]byte{"OFD.xml": root}, encryption: r.encryption}
|
||||||
for name := range files {
|
for name := range files {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if name != "OFD.xml" {
|
if name != "OFD.xml" {
|
||||||
if data, ok := r.files[name]; ok {
|
if data, ok := r.files[name]; ok {
|
||||||
next.files[name] = data
|
next.files[name] = data
|
||||||
@@ -71,30 +89,33 @@ func (r *Reader) ExtractVersion(id string) (*Reader, error) {
|
|||||||
if r.Zip != nil {
|
if r.Zip != nil {
|
||||||
next.Zip = &zip.Reader{Comment: r.Zip.Comment}
|
next.Zip = &zip.Reader{Comment: r.Zip.Comment}
|
||||||
for _, file := range r.Zip.File {
|
for _, file := range r.Zip.File {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
name := cleanPackagePath(file.Name)
|
name := cleanPackagePath(file.Name)
|
||||||
if name != "OFD.xml" && files[name] && !file.FileInfo().IsDir() {
|
if name != "OFD.xml" && files[name] && !file.FileInfo().IsDir() {
|
||||||
next.Zip.File = append(next.Zip.File, file)
|
next.Zip.File = append(next.Zip.File, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := next.initRoot(); err != nil {
|
if err := next.initRootContext(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := next.docStructure(); err != nil {
|
if _, err := next.docStructureContext(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return next, nil
|
return next, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractedVersionRoot 重建版本副本入口,保留元数据及命名空间,移除其他文档与版本列表
|
// extractedVersionRoot 重建版本副本入口,保留元数据及命名空间,移除其他文档与版本列表
|
||||||
// 入参: version 版本描述, files 版本包含的文件
|
// 入参: ctx 取消上下文, version 版本描述, files 版本包含的文件
|
||||||
// 返回: []byte 主入口XML, error 读取或结构错误
|
// 返回: []byte 主入口XML, error 读取、结构或取消错误
|
||||||
func (r *Reader) extractedVersionRoot(version DocumentVersionInfo, files map[string]bool) ([]byte, error) {
|
func (r *Reader) extractedVersionRoot(ctx context.Context, version DocumentVersionInfo, files map[string]bool) ([]byte, error) {
|
||||||
data, err := r.readFile("OFD.xml")
|
data, err := r.readFileViewContext(ctx, "OFD.xml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
root, err := parseEditorXML(data)
|
root, err := parseEditorXMLContext(ctx, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -104,6 +125,9 @@ func (r *Reader) extractedVersionRoot(version DocumentVersionInfo, files map[str
|
|||||||
}
|
}
|
||||||
var patches []editorXMLPatch
|
var patches []editorXMLPatch
|
||||||
for _, child := range root.children {
|
for _, child := range root.children {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if child.matchesOFD("DocBody") && child != body {
|
if child.matchesOFD("DocBody") && child != body {
|
||||||
patches = append(patches, editorXMLPatch{start: child.start, end: child.end})
|
patches = append(patches, editorXMLPatch{start: child.start, end: child.end})
|
||||||
}
|
}
|
||||||
@@ -130,11 +154,14 @@ func (r *Reader) extractedVersionRoot(version DocumentVersionInfo, files map[str
|
|||||||
}
|
}
|
||||||
data = editorPatchXML(data, patches)
|
data = editorPatchXML(data, patches)
|
||||||
if version.Version != "" {
|
if version.Version != "" {
|
||||||
root, err = parseEditorXML(data)
|
root, err = parseEditorXMLContext(ctx, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err = editorXMLAttribute(data, root, "Version", version.Version)
|
data, err = editorXMLAttribute(data, root, "Version", version.Version)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = ctx.Err()
|
||||||
|
}
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
@@ -114,13 +114,6 @@ func (r *Reader) DocumentVersion(id string) (*Reader, error) {
|
|||||||
return next, nil
|
return next, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentEntry 获取指定文档的阅读入口,当前文档保留显式选择,其他文档使用默认版本
|
|
||||||
// 入参: index 文档索引
|
|
||||||
// 返回: string 包内路径, error 选择错误
|
|
||||||
func (r *Reader) documentEntry(index int) (string, error) {
|
|
||||||
return r.documentEntryContext(context.Background(), index)
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentEntryContext 解析指定文档的阅读入口,当前文档保留显式选择
|
// documentEntryContext 解析指定文档的阅读入口,当前文档保留显式选择
|
||||||
// 入参: ctx 取消上下文, index 文档索引
|
// 入参: ctx 取消上下文, index 文档索引
|
||||||
// 返回: string 包内路径, error 选择、读取或取消错误
|
// 返回: string 包内路径, error 选择、读取或取消错误
|
||||||
|
|||||||
Reference in new issue
Block a user