feat(标准支持): 统一命名空间匹配与兼容
build.yaml / build (push) Successful in 47s

This commit is contained in:
xiaoqidun committed 2026-10-09 23:30:39 +08:00
1 parent e9caaa4193
commit f96ef65741
12 files changed
+30 -30

No files matched your search

+1 -1
View File
@@ -68,7 +68,7 @@ func (e *Editor) SetDocumentActions(actions []Action) error {
context = node context = node
} else { } else {
for _, child := range root.children { for _, child := range root.children {
if packageOFDNode(child, child.name.Local) && slices.Contains([]string{"VPreferences", "Bookmarks", "Annotations", "CustomTags", "Attachments", "Extensions"}, child.name.Local) { if child.matchesOFD(child.name.Local) && slices.Contains([]string{"VPreferences", "Bookmarks", "Annotations", "CustomTags", "Attachments", "Extensions"}, child.name.Local) {
patch.start, patch.end = child.start, child.start patch.start, patch.end = child.start, child.start
break break
} }
+3 -3
View File
@@ -181,7 +181,7 @@ func (e *Editor) editAnnotations(index int, ids []string, edit func([]byte, *edi
found := make(map[string]bool, len(ids)) found := make(map[string]bool, len(ids))
remaining := 0 remaining := 0
for _, ref := range root.children { for _, ref := range root.children {
if !packageOFDNode(ref, "Page") { if !ref.matchesOFD("Page") {
continue continue
} }
remaining++ remaining++
@@ -207,7 +207,7 @@ func (e *Editor) editAnnotations(index int, ids []string, edit func([]byte, *edi
var changes []editorXMLPatch var changes []editorXMLPatch
count := 0 count := 0
for _, node := range page.children { for _, node := range page.children {
if !packageOFDNode(node, "Annot") { if !node.matchesOFD("Annot") {
continue continue
} }
count++ count++
@@ -235,7 +235,7 @@ func (e *Editor) editAnnotations(index int, ids []string, edit func([]byte, *edi
} }
sharedFile := false sharedFile := false
for _, other := range root.children { for _, other := range root.children {
if other == ref || !packageOFDNode(other, "Page") || other.child("FileLoc") == nil { if other == ref || !other.matchesOFD("Page") || other.child("FileLoc") == nil {
continue continue
} }
shared, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, other.child("FileLoc")))) shared, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, other.child("FileLoc"))))
+4 -4
View File
@@ -176,7 +176,7 @@ func (e *Editor) annotationXML(index int, id string) ([]byte, error) {
} }
var result []byte var result []byte
for _, ref := range root.children { for _, ref := range root.children {
if !packageOFDNode(ref, "Page") || ref.attr("PageID") != e.pages[index].ID || ref.child("FileLoc") == nil { if !ref.matchesOFD("Page") || ref.attr("PageID") != e.pages[index].ID || ref.child("FileLoc") == nil {
continue continue
} }
file, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, ref.child("FileLoc")))) file, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, ref.child("FileLoc"))))
@@ -192,7 +192,7 @@ func (e *Editor) annotationXML(index int, id string) ([]byte, error) {
return nil, err return nil, err
} }
for _, node := range page.children { for _, node := range page.children {
if !packageOFDNode(node, "Annot") || node.attr("ID") != id { if !node.matchesOFD("Annot") || node.attr("ID") != id {
continue continue
} }
if result != nil { if result != nil {
@@ -248,7 +248,7 @@ func (e *Editor) appendAnnotations(index int, annotations []byte, generated bool
return err return err
} }
for _, item := range root.children { for _, item := range root.children {
if packageOFDNode(item, "Page") && item.attr("PageID") == e.pages[index].ID { if item.matchesOFD("Page") && item.attr("PageID") == e.pages[index].ID {
ref = item ref = item
loc := item.child("FileLoc") loc := item.child("FileLoc")
if loc == nil { if loc == nil {
@@ -285,7 +285,7 @@ func (e *Editor) appendAnnotations(index int, annotations []byte, generated bool
file := existing file := existing
if file != "" { if file != "" {
for _, other := range root.children { for _, other := range root.children {
if other == ref || !packageOFDNode(other, "Page") || other.child("FileLoc") == nil { if other == ref || !other.matchesOFD("Page") || other.child("FileLoc") == nil {
continue continue
} }
shared, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, other.child("FileLoc")))) shared, err := editorPageLocation(reader, nil, name, strings.TrimSpace(editorImportText(data, other.child("FileLoc"))))
+1 -1
View File
@@ -217,7 +217,7 @@ func (e *Editor) editAttachment(id string, change func([]byte, *editorXML, map[s
var found *editorXML var found *editorXML
if root != nil { if root != nil {
for _, child := range root.children { for _, child := range root.children {
if packageOFDNode(child, "Attachment") && child.attr("ID") == id { if child.matchesOFD("Attachment") && child.attr("ID") == id {
if found != nil { if found != nil {
return fmt.Errorf("duplicate attachment ID: %s", id) return fmt.Errorf("duplicate attachment ID: %s", id)
} }
+1 -1
View File
@@ -347,7 +347,7 @@ func (n *editorCompositeNode) preserveActionRegions(matrix Matrix) (bool, error)
} }
var targets []*editorXML var targets []*editorXML
for _, action := range actions.children { for _, action := range actions.children {
if action.name.Local != "Action" || action.name.Space != "" && action.name.Space != actions.name.Space && action.name.Space != ofdNamespace2016 { if !action.matchesOFD("Action") {
continue continue
} }
if action.attr("Event") == "CLICK" && action.child("Region") == nil { if action.attr("Event") == "CLICK" && action.child("Region") == nil {
+1 -1
View File
@@ -123,7 +123,7 @@ func editorCustomDatas(data []byte, info *editorXML, values *CustomDatas) ([]byt
var nodes []*editorXML var nodes []*editorXML
if container != nil { if container != nil {
for _, node := range container.children { for _, node := range container.children {
if node.name.Local == "CustomData" && (node.name.Space == ofdNamespace2016 || node.name.Space == container.name.Space) { if node.matchesOFD("CustomData") {
nodes = append(nodes, node) nodes = append(nodes, node)
byName[node.attr("Name")] = append(byName[node.attr("Name")], node) byName[node.attr("Name")] = append(byName[node.attr("Name")], node)
} }
+7
View File
@@ -20,6 +20,13 @@ import (
"strconv" "strconv"
) )
// matchesOFD 匹配OFD节点,兼容与父节点一致的未知命名空间
// 入参: name 节点名称
// 返回: bool 是否匹配
func (n *editorXML) matchesOFD(name string) bool {
return n.name.Local == name && (classifyOFDNamespace(n.name.Space) != ofdXMLUnknown || n.parent != nil && n.name.Space == n.parent.name.Space)
}
// textXML 按所在节点的命名空间编码文本节点 // textXML 按所在节点的命名空间编码文本节点
// 入参: name 节点名称, value 文本 // 入参: name 节点名称, value 文本
// 返回: []byte XML片段 // 返回: []byte XML片段
+4 -4
View File
@@ -119,10 +119,10 @@ func (e *Editor) UpdateOutline(path []int, title string, page int) error {
if actions != nil { if actions != nil {
var removals []editorXMLPatch var removals []editorXMLPatch
for _, action := range actions.children { for _, action := range actions.children {
if action.name.Space != actions.name.Space && action.name.Space != ofdNamespace2016 && action.name.Space != "" { if !action.matchesOFD("Action") {
continue continue
} }
if action.name.Local == "Action" && action.child("Goto") != nil { if action.child("Goto") != nil {
removals = append(removals, editorXMLPatch{action.start - actions.open, action.end - actions.open, nil}) removals = append(removals, editorXMLPatch{action.start - actions.open, action.end - actions.open, nil})
} }
} }
@@ -315,7 +315,7 @@ func (e *Editor) outlineAction(page int) []byte {
func editorOutlineChildren(node *editorXML) []*editorXML { func editorOutlineChildren(node *editorXML) []*editorXML {
var children []*editorXML var children []*editorXML
for _, child := range node.children { for _, child := range node.children {
if child.name.Local == "OutlineElem" && (child.name.Space == node.name.Space || child.name.Space == ofdNamespace2016 || child.name.Space == "") { if child.matchesOFD("OutlineElem") {
children = append(children, child) children = append(children, child)
} }
} }
@@ -425,7 +425,7 @@ func (e *Editor) withOutlines(data []byte) ([]byte, error) {
walk = func(node *editorXML) { walk = func(node *editorXML) {
if actions := node.child("Actions"); actions != nil { if actions := node.child("Actions"); actions != nil {
for _, action := range actions.children { for _, action := range actions.children {
if action.name.Local != "Action" || action.name.Space != actions.name.Space && action.name.Space != ofdNamespace2016 && action.name.Space != "" { if !action.matchesOFD("Action") {
continue continue
} }
if target := action.child("Goto"); target != nil { if target := action.child("Goto"); target != nil {
+2 -2
View File
@@ -178,7 +178,7 @@ func (e *Editor) sourcePartsPrepared(progress editorProgress, generated map[stri
} }
originals := make(map[string]*editorXML, len(pages.children)) originals := make(map[string]*editorXML, len(pages.children))
for _, child := range pages.children { for _, child := range pages.children {
if packageOFDNode(child, "Page") { if child.matchesOFD("Page") {
id := child.attr("ID") id := child.attr("ID")
if originals[id] == nil { if originals[id] == nil {
originals[id] = child originals[id] = child
@@ -200,7 +200,7 @@ func (e *Editor) sourcePartsPrepared(progress editorProgress, generated map[stri
} }
position := 0 position := 0
for _, child := range pages.children { for _, child := range pages.children {
if !packageOFDNode(child, "Page") { if !child.matchesOFD("Page") {
continue continue
} }
var entry []byte var entry []byte
+3 -3
View File
@@ -92,7 +92,7 @@ func (n *editorXML) child(name string) *editorXML {
// 返回: *editorXML 节点,不存在时为nil // 返回: *editorXML 节点,不存在时为nil
func (n *editorXML) childAt(name string, index int) *editorXML { func (n *editorXML) childAt(name string, index int) *editorXML {
for _, child := range n.children { for _, child := range n.children {
if child.name.Local == name && (child.name.Space == n.name.Space || child.name.Space == ofdNamespace2016 || child.name.Space == "") { if child.matchesOFD(name) {
if index == 0 { if index == 0 {
return child return child
} }
@@ -512,7 +512,7 @@ func editorXMLMergeNamespace(data []byte, node *editorXML, oldXML, newXML []byte
matching := len(node.children) > 0 && len(node.children) == len(oldNode.children) && len(node.children) == len(newNode.children) matching := len(node.children) > 0 && len(node.children) == len(oldNode.children) && len(node.children) == len(newNode.children)
if matching { if matching {
for i, child := range node.children { for i, child := range node.children {
if !packageOFDNode(child, oldNode.children[i].name.Local) || child.name.Local != newNode.children[i].name.Local { if !child.matchesOFD(oldNode.children[i].name.Local) || child.name.Local != newNode.children[i].name.Local {
matching = false matching = false
break break
} }
@@ -567,7 +567,7 @@ func editorXMLMergeContent(data []byte, node *editorXML, oldXML []byte, oldNode
groups := func(root *editorXML, encoded bool) map[string][]*editorXML { groups := func(root *editorXML, encoded bool) map[string][]*editorXML {
result := make(map[string][]*editorXML) result := make(map[string][]*editorXML)
for _, child := range root.children { for _, child := range root.children {
if encoded || packageOFDNode(child, child.name.Local) { if encoded || child.matchesOFD(child.name.Local) {
result[child.name.Local] = append(result[child.name.Local], child) result[child.name.Local] = append(result[child.name.Local], child)
} }
} }
+2 -9
View File
@@ -38,13 +38,6 @@ func packagePagePath(directory, id string) string {
return path.Join(directory, "Pages", "Page_"+id, "Content.xml") return path.Join(directory, "Pages", "Page_"+id, "Content.xml")
} }
// packageOFDNode 识别包索引中的OFD节点,兼容与父节点同命名空间的已知字段
// 入参: node XML节点, name 节点名称
// 返回: bool 是否为OFD节点
func packageOFDNode(node *editorXML, name string) bool {
return node.name.Local == name && (classifyOFDNamespace(node.name.Space) != ofdXMLUnknown || node.parent != nil && node.name.Space == node.parent.name.Space)
}
// packageName 为新增条目分配文档内路径,不覆盖原文件或本次资源 // packageName 为新增条目分配文档内路径,不覆盖原文件或本次资源
// 入参: relative 文档相对路径 // 入参: relative 文档相对路径
// 返回: string 未占用路径 // 返回: string 未占用路径
@@ -125,7 +118,7 @@ func mergePackageResources(reader *Reader, parts map[string][]byte, doc *Documen
var content []byte var content []byte
for _, node := range group.children { for _, node := range group.children {
if target != nil && slices.ContainsFunc(target.children, func(old *editorXML) bool { if target != nil && slices.ContainsFunc(target.children, func(old *editorXML) bool {
return packageOFDNode(old, node.name.Local) && old.attr("ID") == node.attr("ID") return old.matchesOFD(node.name.Local) && old.attr("ID") == node.attr("ID")
}) { }) {
continue continue
} }
@@ -153,7 +146,7 @@ func mergePackageResources(reader *Reader, parts map[string][]byte, doc *Documen
} }
position := root.close position := root.close
for _, child := range root.children { for _, child := range root.children {
if packageOFDNode(child, child.name.Local) && slices.Index(order, child.name.Local) > slices.Index(order, group.name.Local) { if child.matchesOFD(child.name.Local) && slices.Index(order, child.name.Local) > slices.Index(order, group.name.Local) {
position = child.start position = child.start
break break
} }
+1 -1
View File
@@ -28,7 +28,7 @@ const (
ofdXML2016 ofdXML2016
) )
// ofdXMLNamespace 标识XML节点采用的OFD命名空间 // ofdXMLNamespace 标识XML命名空间,不代表文档版本或功能支持范围
type ofdXMLNamespace uint8 type ofdXMLNamespace uint8
// classifyOFDNamespace 识别OFD命名空间,未声明与未知版本分别处理 // classifyOFDNamespace 识别OFD命名空间,未声明与未知版本分别处理