我从以下结构中编写XML:
type OrderLine struct {
LineNumber string `xml:"LineNumber"`
Product string `xml:"Product"`
Ref string `xml:"Ref"`
Quantity string `xml:"Quantity"`
Price string `xml:"Price"`
LineTotalGross string `xml:"LineTotalGross"`
}
如果Ref
字段为空,我想要显示的元素,但是要自动关闭,即
<Ref />
和不:
<Ref></Ref>
AFAIK,这两个在语义上是等价的,但我更喜欢自动关闭标签,因为它匹配其他系统的输出。这可能吗?
答案 0 :(得分:1)
我找到了一种方法来做“黑客”元帅包,但我没有测试它。如果您希望我向您显示链接,请立即告诉我,然后将其发布在此回复的评论中。
我做了一些手动代码:
package main
import (
"encoding/xml"
"fmt"
"regexp"
"strings"
)
type ParseXML struct {
Person struct {
Name string `xml:"Name"`
LastName string `xml:"LastName"`
Test string `xml:"Abc"`
} `xml:"Person"`
}
func main() {
var err error
var newPerson ParseXML
newPerson.Person.Name = "Boot"
newPerson.Person.LastName = "Testing"
var bXml []byte
var sXml string
bXml, err = xml.Marshal(newPerson)
checkErr(err)
sXml = string(bXml)
r, err := regexp.Compile(`<([a-zA-Z0-9]*)><(\\|\/)([a-zA-Z0-9]*)>`)
checkErr(err)
matches := r.FindAllString(sXml, -1)
fmt.Println(sXml)
if len(matches) > 0 {
r, err = regexp.Compile("<([a-zA-Z0-9]*)>")
for i := 0; i < len(matches); i++ {
xmlTag := r.FindString(matches[i])
xmlTag = strings.Replace(xmlTag, "<", "", -1)
xmlTag = strings.Replace(xmlTag, ">", "", -1)
sXml = strings.Replace(sXml, matches[i], "<"+xmlTag+" />", -1)
}
}
fmt.Println("")
fmt.Println(sXml)
}
func checkErr(chk error) {
if chk != nil {
panic(chk)
}
}
答案 1 :(得分:0)
这篇文章提供了两种不依赖于正则表达式的解决方案,并解释了两者之间的区别。
第一个版本对内存友好,但对 CPU 不利。它实现了一个编写器,通过在缓冲字节内替换来替换搜索的出现。它尝试尽快写入数据,防止内存中的大量分配。 这不是 CPU 的最佳用法,因为 if 会多次扫描相同的数据。
package main
import (
"bytes"
"encoding/xml"
"fmt"
"io"
"os"
)
// Person represents a <person> node in the XML
type Person struct {
XMLName xml.Name `xml:"Players"`
DataItems []dataItem `xml:"DataItem"`
}
// Skill represents a <skill> node in the XML
type dataItem struct {
XMLName xml.Name `xml:"DataItem"`
Name string `xml:"skillName,attr"`
YearsPracticed int64 `xml:"practice,attr"`
Level string `xml:"level,attr"`
}
func main() {
players := Person{
DataItems: []dataItem{
{Name: "Soccer", YearsPracticed: 3, Level: "Newbie"},
{Name: "Basketball", YearsPracticed: 4, Level: "State"},
{Name: "Baseball", YearsPracticed: 10, Level: "National"},
},
}
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
dst := &Replace{
Writer: os.Stdout,
Search: []byte("></DataItem>"),
Replace: []byte("/>"),
}
defer dst.Flush()
enc := xml.NewEncoder(dst)
enc.Indent("", " ")
if err := enc.Encode(players); err != nil {
fmt.Printf("error: %v\n", err)
}
}
type Replace struct {
io.Writer
Search []byte
Replace []byte
buf []byte
}
func (s *Replace) Write(b []byte) (n int, err error) {
s.buf = append(s.buf, b...)
s.buf = bytes.ReplaceAll(s.buf, s.Search, s.Replace)
if len(s.buf) > len(s.Search) {
w := s.buf[:len(s.buf)-len(s.Search)]
n, err = s.Writer.Write(w)
s.buf = s.buf[n:]
}
return len(b), err
}
func (s *Replace) Flush() (err error) {
var n int
n, err = s.Writer.Write(s.buf)
s.buf = s.buf[n:]
return
}
第二个版本对 cpu 友好但内存不利,因为它加载整个数据在内存中修改。
package main
import (
"bytes"
"encoding/xml"
"fmt"
"os"
)
// Person represents a <person> node in the XML
type Person struct {
XMLName xml.Name `xml:"Players"`
DataItems []dataItem `xml:"DataItem"`
}
// Skill represents a <skill> node in the XML
type dataItem struct {
XMLName xml.Name `xml:"DataItem"`
Name string `xml:"skillName,attr"`
YearsPracticed int64 `xml:"practice,attr"`
Level string `xml:"level,attr"`
}
func main() {
players := Person{
DataItems: []dataItem{
{Name: "Soccer", YearsPracticed: 3, Level: "Newbie"},
{Name: "Basketball", YearsPracticed: 4, Level: "State"},
{Name: "Baseball", YearsPracticed: 10, Level: "National"},
},
}
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
players.DataItems = append(players.DataItems, players.DataItems...)
out := new(bytes.Buffer)
enc := xml.NewEncoder(out)
enc.Indent("", " ")
if err := enc.Encode(players); err != nil {
fmt.Printf("error: %v\n", err)
}
b := bytes.ReplaceAll(out.Bytes(), []byte("></DataItem>"), []byte("/>"))
os.Stdout.Write(b)
}
根据您的执行环境选择一个。