feat(参照标准): 规范元数据与导航解析
build.yaml / build (push) Successful in 52s

This commit is contained in:
xiaoqidun committed 2026-10-12 12:18:30 +08:00
1 parent 2a7fbd7f61
commit 47b1957e72
3 files changed
+214 -25

No files matched your search

+81 -19
View File
@@ -156,7 +156,51 @@ func decodeOFDActions(d *xml.Decoder, start xml.StartElement, actions *[]Action)
})
}
// UnmarshalXML 解析跳转目标
// UnmarshalXML 读取事件、区域和动作内容,忽略外部同名节点
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (action *Action) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*action = Action{Event: attrValue(start, "Event")}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
var target any
switch node.Name.Local {
case "Region":
target = &action.Region
case "Goto":
target = &action.Goto
case "URI":
target = &action.URI
case "GotoA":
target = &action.GotoA
case "Sound":
target = &action.Sound
case "Movie":
target = &action.Movie
default:
return d.Skip()
}
return d.DecodeElement(target, &node)
})
}
// UnmarshalXML 读取文档内跳转目标或书签,不采用外部扩展中的同名目标
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (action *Goto) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*action = Goto{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
switch node.Name.Local {
case "Dest":
return d.DecodeElement(&action.Dest, &node)
case "Bookmark":
return d.DecodeElement(&action.Bookmark, &node)
default:
return d.Skip()
}
})
}
// UnmarshalXML 解析跳转目标,忽略外部坐标字段
// 入参: d XML解码器, start 起始节点
// 返回: error 错误信息
func (dest *Dest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
@@ -196,7 +240,24 @@ func (dest *Dest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*target = v
}
}
if err := d.DecodeElement(&value, &start); err != nil {
if err := decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
var target **float64
switch node.Name.Local {
case "Left":
target = &value.Left
case "Right":
target = &value.Right
case "Top":
target = &value.Top
case "Bottom":
target = &value.Bottom
case "Zoom":
target = &value.Zoom
default:
return d.Skip()
}
return d.DecodeElement(target, &node)
}); err != nil {
return err
}
if value.Left != nil {
@@ -231,6 +292,7 @@ func (dest *Dest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
func (m *Movie) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type movie Movie
value := movie{Operator: "Play"}
start = ofdXMLStart(start)
if err := d.DecodeElement(&value, &start); err != nil {
return err
}
@@ -238,18 +300,25 @@ func (m *Movie) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return nil
}
// UnmarshalXML 解析动作区域分路径并保留指令顺序
// UnmarshalXML 读取动作区域中的OFD分路径,跳过外部扩展区域
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (region *Region) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*region = Region{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
if node.Name.Local != "Area" {
return d.Skip()
}
return d.DecodeElement(&region.Area, &node)
})
}
// UnmarshalXML 按原顺序读取区域指令,外部同名节点不参与路径绘制
// 入参: d XML解码器, start 起始节点
// 返回: error 错误信息
func (a *RegionArea) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*a = RegionArea{Start: attrValue(start, "Start")}
for {
tok, err := d.Token()
if err != nil {
return err
}
switch node := tok.(type) {
case xml.StartElement:
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
command := RegionCommand{
Type: node.Name.Local,
Point1: attrValue(node, "Point1"),
@@ -262,15 +331,8 @@ func (a *RegionArea) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
EndPoint: attrValue(node, "EndPoint"),
}
a.Command = append(a.Command, command)
if err := d.Skip(); err != nil {
return err
}
case xml.EndElement:
if node.Name.Local == start.Name.Local {
return nil
}
}
}
return d.Skip()
})
}
// gotoDest 获取文档内跳转目标
+71 -6
View File
@@ -18,6 +18,7 @@ import (
"encoding/xml"
"fmt"
"path"
"strconv"
"strings"
)
@@ -388,17 +389,81 @@ func (a *Attachment) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return nil
}
// UnmarshalXML 解析大纲节点并应用默认值
// UnmarshalXML 读取OFD书签列表,跳过外部同名条目
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (bookmarks *Bookmarks) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*bookmarks = Bookmarks{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
if node.Name.Local != "Bookmark" {
return d.Skip()
}
return d.DecodeElement(&bookmarks.Bookmark, &node)
})
}
// UnmarshalXML 读取书签名称及目标,不使用外部扩展中的跳转信息
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (bookmark *Bookmark) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*bookmark = Bookmark{Name: attrValue(start, "Name")}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
if node.Name.Local != "Dest" {
return d.Skip()
}
return d.DecodeElement(&bookmark.Dest, &node)
})
}
// UnmarshalXML 读取OFD大纲列表,跳过外部同名节点
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (outlines *Outlines) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*outlines = Outlines{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
if node.Name.Local != "OutlineElem" {
return d.Skip()
}
return d.DecodeElement(&outlines.OutlineElem, &node)
})
}
// UnmarshalXML 解析大纲节点、子大纲和动作,并应用默认展开状态
// 入参: d XML解码器, start 起始节点
// 返回: error 错误信息
func (o *OutlineElem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type outlineElem OutlineElem
value := outlineElem{Expanded: true}
if err := d.DecodeElement(&value, &start); err != nil {
*o = OutlineElem{Title: attrValue(start, "Title"), Expanded: true}
for _, attr := range start.Attr {
if attr.Name.Space != "" {
continue
}
value := strings.TrimSpace(attr.Value)
var err error
switch attr.Name.Local {
case "Count":
if value != "" {
o.Count, err = strconv.Atoi(value)
}
case "Expanded":
o.Expanded = false
if value != "" {
o.Expanded, err = strconv.ParseBool(value)
}
}
if err != nil {
return err
}
*o = OutlineElem(value)
return nil
}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
switch node.Name.Local {
case "Actions":
return decodeOFDActions(d, node, &o.Actions)
case "OutlineElem":
return d.DecodeElement(&o.OutlineElem, &node)
default:
return d.Skip()
}
})
}
// UnmarshalXML 解析文档权限并应用默认值
+62
View File
@@ -106,3 +106,65 @@ func (body *DocBody) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement)
return d.Skip()
})
}
// UnmarshalXML 读取文档元数据,不将外部同名字段作为OFD信息
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (info *DocInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*info = DocInfo{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
var target any
switch node.Name.Local {
case "DocID":
target = &info.DocID
case "Title":
target = &info.Title
case "Author":
target = &info.Author
case "Subject":
target = &info.Subject
case "Abstract":
target = &info.Abstract
case "CreationDate":
target = &info.CreationDate
case "ModDate":
target = &info.ModDate
case "Creator":
target = &info.Creator
case "CreatorVersion":
target = &info.CreatorVersion
case "CustomDatas":
target = &info.CustomDatas
default:
return d.Skip()
}
return d.DecodeElement(target, &node)
})
}
// UnmarshalXML 按原顺序读取OFD自定义字段,跳过外部扩展条目
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (data *CustomDatas) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*data = CustomDatas{}
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
if node.Name.Local != "CustomData" {
return d.Skip()
}
return d.DecodeElement(&data.CustomData, &node)
})
}
// UnmarshalXML 读取自定义字段的名称和文本,忽略带命名空间的属性
// 入参: d XML解码器, start 起始节点
// 返回: error 解析错误
func (data *CustomData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type customData CustomData
var value customData
start = ofdXMLStart(start)
if err := d.DecodeElement(&value, &start); err != nil {
return err
}
*data = CustomData(value)
return nil
}