// Copyright 2025-2026 肖其顿 (XIAO QI DUN) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ofdgo import ( "encoding/xml" "fmt" ) // ofdCreator 标识本库生成的文档 const ofdCreator = "xiaoqidun/ofdgo" // OFD OFD入口结构 // 代表OFD文档的根节点 type OFD struct { XMLName xml.Name `xml:"OFD"` Version string `xml:"Version,attr"` DocType string `xml:"DocType,attr"` DocBody []DocBody `xml:"DocBody"` } // DocBody 文档体信息 // 包含文档元数据和根节点路径 type DocBody struct { DocInfo DocInfo `xml:"DocInfo"` DocRoot string `xml:"DocRoot"` Signatures string `xml:"Signatures"` versioned bool } // DocInfo 文档元数据 type DocInfo struct { DocID string `xml:"DocID"` Title string `xml:"Title"` Author string `xml:"Author"` Subject string `xml:"Subject"` Abstract string `xml:"Abstract"` CreationDate string `xml:"CreationDate"` ModDate string `xml:"ModDate"` Creator string `xml:"Creator"` CreatorVersion string `xml:"CreatorVersion"` CustomDatas *CustomDatas `xml:"CustomDatas"` } // CustomDatas 自定义数据集合 type CustomDatas struct { CustomData []CustomData `xml:"CustomData"` } // CustomData 自定义数据项 type CustomData struct { Name string `xml:"Name,attr"` Value string `xml:",chardata"` sourceIndex int } // UnmarshalXML 读取主入口,区分标准文档条目与扩展中的同名节点 // 入参: decoder XML解码器, start 起始节点 // 返回: error 解析错误 func (ofd *OFD) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error { if start.Name.Local != "OFD" { return fmt.Errorf("expected OFD root, got %s", start.Name.Local) } *ofd = OFD{XMLName: start.Name, Version: attrValue(start, "Version"), DocType: attrValue(start, "DocType")} return decodeOFDChildren(decoder, start, func(d *xml.Decoder, node xml.StartElement) error { if node.Name.Local != "DocBody" { return d.Skip() } var body DocBody if err := d.DecodeElement(&body, &node); err != nil { return err } ofd.DocBody = append(ofd.DocBody, body) return nil }) } // UnmarshalXML 读取文档入口并记录版本列表是否存在,版本描述在选择时读取 // 入参: decoder XML解码器, start 起始节点 // 返回: error 解析错误 func (body *DocBody) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error { *body = DocBody{} return decodeOFDChildren(decoder, start, func(d *xml.Decoder, node xml.StartElement) error { switch node.Name.Local { case "DocInfo": return d.DecodeElement(&body.DocInfo, &node) case "DocRoot": return d.DecodeElement(&body.DocRoot, &node) case "Signatures": return d.DecodeElement(&body.Signatures, &node) case "Versions": body.versioned = true } return d.Skip() }) }