I am trying to write an XML parser which will load a data from XML file and convert it to golang structs, but apparently it is not working and I have no idea why. I wrote a test to troubleshoot it, but it didn't have me much clue. What I know is that XML is parsed, but the output Quote structs are empty.
I read in different topic that "The problem is that only exported fields can be marshaled/unmarshaled." but I have this covered - all fields starts with capital letter.
I run of ideas what I am doing wrong here. Any ideas?
Function code
package main
import (
"encoding/xml"
"fmt"
"io"
"log"
"os"
)
type Quotes struct {
Quote []Quote `xml:"quote"`
}
type Quote struct {
Ver string `xml:"ver"`
Content string `xml:"content"`
Author string `xml:"author"`
}
func (sq *Quote) String() string {
return fmt.Sprintf("%s - %s", sq.Author, sq.Content)
}
func LoadQuotes(pathToXmlFile string) ([]Quote, error) {
xmlFile, err := os.Open(pathToXmlFile)
if err != nil {
log.Fatalf("%v", err)
}
defer xmlFile.Close()
byteValue, _ := io.ReadAll(xmlFile)
// Prints to help troubleshoot the issue
fmt.Println("Read data:")
fmt.Printf("%s\n", string(byteValue))
fmt.Println("End of read data ---")
var quotes Quotes
if err := xml.Unmarshal(byteValue, "es); err != nil {
log.Fatal(err)
return nil, err
}
return quotes.Quote, nil
}
Test code
package main
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestLoadQuotes(t *testing.T) {
// Create a temporary test file with some sample quotes
testData := `<?xml version='1.0' encoding='utf-8'?>
<quotes>
<quote ver="1.0" content="Quote 1" author="Author 1"/>
<quote ver="1.0" content="Quote 2" author="Author 2"/>
</quotes>`
tmpFile, err := os.CreateTemp("", "test.xml")
if err != nil {
t.Fatalf("Error creating temporary file: %v", err)
}
defer os.Remove(tmpFile.Name())
_, err = tmpFile.Write([]byte(testData))
if err != nil {
t.Fatalf("Error writing to temporary file: %v", err)
}
tmpFile.Close()
// Call the function with the temporary file
quotes, err := LoadQuotes(tmpFile.Name())
require.NoError(t, err)
expected := []Quote{
{Ver: "1.0", Content: "Quote 1", Author: "Author 1"},
{Ver: "1.0", Content: "Quote 2", Author: "Author 2"},
}
require.Len(t, quotes, len(expected))
for i, quote := range quotes {
// HERE THE TEST FAILS, AUTHOR AND CONTENT IS EMPTY
require.Equal(t, expected[i].String(), quote.String())
}
}
Test result
Read data:
<?xml version='1.0' encoding='utf-8'?>
<quotes>
<quote ver="1.0" content="Quote 1" author="Author 1"/>
<quote ver="1.0" content="Quote 2" author="Author 2"/>
</quotes>
End of read data ---
--- FAIL: TestLoadQuotes (0.00s)
xml_test.go:43:
Error Trace: /home/sebastian/repo/blog/xml_test.go:43
Error: Not equal:
expected: "Author 1 - Quote 1"
actual : " - "
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-Author 1 - Quote 1
+ -
Test: TestLoadQuotes
FAIL
exit status 1