通过UnMarshal和MarshalIndent往返XML

时间:2018-10-05 16:06:07

标签: xml go marshalling unmarshalling

我想快速创建一个使用golang的xml.MarshalIndent()格式化XML数据的实用程序

但是this code

package main

import (
    "encoding/xml"
    "fmt"
)

func main() {

    type node struct {
        XMLName  xml.Name
        Attrs    []xml.Attr `xml:",attr"`
        Text     string     `xml:",chardata"`
        Children []node     `xml:",any"`
    }

    x := node{}
    _ = xml.Unmarshal([]byte(doc), &x)
    buf, _ := xml.MarshalIndent(x, "", "  ") // prefix, indent

    fmt.Println(string(buf))
}

const doc string = `<book lang="en">
     <title>The old man and the sea</title>
       <author>Hemingway</author>
</book>`

生产

<book>&#xA;     &#xA;       &#xA;
  <title>The old man and the sea</title>
  <author>Hemingway</author>
</book>

请注意<book>开头元素之后的无关紧要的东西。

  • 我已经失去了属性-为什么?
  • 我想避免收集虚假的元素间字符数据-如何?

1 个答案:

答案 0 :(得分:1)

对于初学者来说,您没有正确使用struct标记属性,因此这是一个简单的解决方法。

来自https://godoc.org/encoding/xml#Unmarshal

  
      
  • 如果XML元素具有先前版本未处理的属性   规则,并且结构具有包含相关标签的字段,该标签包含   “,any,attr”,Unmarshal将属性值记录在第一个   这样的领域。
  •   

第二,因为标记xml:",chardata"甚至没有通过UnmarshalXML接口的xml.Unmarshaller传递该字段,所以您不能简单地为Text创建新类型并按照同一文档中所述为该接口实现该接口。 (请注意,除了[] byte或string以外的任何其他类型都将导致错误)

  
      
  • 如果XML元素包含字符数据,则该数据为   累积在具有标签“,chardata”的第一个结构字段中。   struct字段的类型可以为[] byte或字符串。   如果没有这样的字段,字符数据将被丢弃。
  •   

因此,处理不想要的字符的最简单方法是在事后更换它们。

此处的完整代码示例:https://play.golang.org/p/VSDskgfcLng

var Replacer = strings.NewReplacer("&#xA;","","&#x9;","","\n","","\t","")

func recursiveReplace(n *Node) {
    n.Text = Replacer.Replace(n.Text)
    for i := range n.Children {
        recursiveReplace(&n.Children[i])
    }
}

理论上可以为xml.Unmarshaller实现Node接口,但是您不仅必须处理手动xml解析,还必须处理它是递归结构的事实。事实结束后,最简单的方法就是删除不需要的字符。