Golang 解码 MusicXML

huangapple go评论72阅读模式
英文:

Golang Decode MusicXML

问题

我正在编写一个程序,可以读取完整的MusicXML文件,对其进行编辑,并将新文件写出。我正在使用xml.Decode将数据读入MusicXML文件的结构体中,但运行时似乎没有任何反应。我尝试将Decode对象打印到屏幕上,但打印出来的是一个由字节组成的结构体。

我查看了xml包的页面,似乎找不到任何关于Decode函数的线程。我尝试根据我找到的一些指针使用UnMarshall,但没有成功(大多数线程都比较旧,所以也许UnMarshall在实现Decode之后有了一些不同的用法)。

这是输入函数:

func ImportXML(infile string) *xml.Decoder {
    // 读取音乐XML文件到内存
    f, err := os.Open(infile)
    if err != nil {
        fmt.Fprintf(os.Stderr, "打开音乐XML文件时出错:%v\n", err)
        os.Exit(1)
    }
    defer f.Close()
    fmt.Println("\n\t正在读取musicXML文件...")
    song := xml.NewDecoder(io.Reader(f))
    // 必须传递一个接口指针给Decode
    err = song.Decode(&Score{})
    if err != nil {
        fmt.Fprintf(os.Stderr, "将musicXML文件分配给结构体时出错:%v\n", err)
        os.Exit(1)
    }
    return song
}

这是前几个结构体(其余的结构体遵循相同的格式):

type Score struct {
    Work           Work           `xml:"work"`
    Identification Identification `xml:"identification"`
    Defaults       Defaults       `xml:"defaults"`
    Credit         Credit         `xml:"credit"`
    Partlist       []Scorepart    `xml:"score-part"`
    Part           []Part         `xml:"part"`
}

// 名称和其他标识
type Work struct {
    Number string `xml:"work-number"`
    Title  string `xml:"work-title"`
}

type Identification struct {
    Type     string     `xml:"type,attr"`
    Creator  string     `xml:"creator"`
    Software string     `xml:"software"`
    Date     string     `xml:"encoding-date"`
    Supports []Supports `xml:"supports"`
    Source   string     `xml:"source"`
}

我非常感谢任何见解

<details>
<summary>英文:</summary>

I am writing a program that can read in a complete MusicXML file, edit it, and write a new file out. I am using xml.Decode to read the data into a struct for the MusicXML file, but when I run it nothing seems to happen. I tried printing the Decode object to the screen, but it printed a struct full of bytes.

I&#39;ve looked over the xml package page and I can&#39;t seem to find any threads covering the Decode function. I tried using UnMarshall according to some of the pointers I found, but that didn&#39;t work (most of those threads were older, so maybe UnMarshall works a bit differently since Decode was implemented?).

Here&#39;s the input function:

    func ImportXML(infile string) *xml.Decoder {
    	// Reads music xml file to memory
    	f, err := os.Open(infile)
    	if err != nil {
    		fmt.Fprintf(os.Stderr, &quot;Error opening music xml file: %v\n&quot;, err)
    		os.Exit(1)
    	}
    	defer f.Close()
    	fmt.Println(&quot;\n\tReading musicXML file...&quot;)
    	song := xml.NewDecoder(io.Reader(f))
    	// must pass an interface pointer to Decode
    	err = song.Decode(&amp;Score{})
    	if err != nil {
    		fmt.Fprintf(os.Stderr, &quot;Error assigning musicXML file to struct: %v\n&quot;, err)
    		os.Exit(1)
    	}
    	return song
    }


Here&#39;s the first few structs (the rest follow the same format):

    type Score struct {
    	Work           Work           `xml:&quot;work&quot;`
    	Identification Identification `xml:&quot;identification&quot;`
    	Defaults       Defaults       `xml:&quot;defaults&quot;`
    	Credit         Credit         `xml:&quot;credit&quot;`
    	Partlist       []Scorepart    `xml:&quot;score-part&quot;`
    	Part           []Part         `xml:&quot;part&quot;`
    }
    
    // Name and other idenfication
    type Work struct {
    	Number string `xml:&quot;work-number&quot;`
    	Title  string `xml:&quot;work-title&quot;`
    }
    
    type Identification struct {
    	Type     string     `xml:&quot;type,attr&quot;`
    	Creator  string     `xml:&quot;creator&quot;`
    	Software string     `xml:&quot;software&quot;`
    	Date     string     `xml:&quot;encoding-date&quot;`
    	Supports []Supports `xml:&quot;supports&quot;`
    	Source   string     `xml:&quot;source&quot;`
    }

I greatly appreciate any insight.

</details>


# 答案1
**得分**: 1

我认为你误解了解码器的行为它将 XML 解码为你传递给 `Decode` 方法的对象

```go
song := xml.NewDecoder(io.Reader(f))
score := Score{}
err = song.Decode(&score)
// 解码后的文档在 score 中,而不是在 song 中
return score

你把解码器当作包含文档的对象处理,但它只是一个解码器。它用于解码。为了在代码中更清晰,它的名称不应该是 song,可以命名为 decoderscoreDecoder 或其他适当的名称。你几乎肯定不想从函数中返回一个 *xml.Decoder*,而是返回解码后的 Score 对象。

英文:

I think you've misunderstood the behavior of the decoder: it decodes XML into the object you pass to Decode:

song := xml.NewDecoder(io.Reader(f))
score := Score{}
err = song.Decode(&amp;score)
// Decoded document is in score, *NOT* in song
return score

You're treating the decoder as if it will contain your document, but it's just a decoder. It decodes. To make it clearer in code, it should not be named song - it should be named, say, decoder or scoreDecoder or what have you. You almost certainly don't want to return an *xml.Decoder* from your function, but rather the decoded Score.

huangapple
  • 本文由 发表于 2017年9月14日 01:20:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/46203443.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定