将XML解组为[]structs,并使用xml.Name。

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

unmarshal xml to []structs with xml.Name

问题

问题

我需要将来自第三方应用程序的XML解组到我的GO结构中。

我尝试过的方法

我创建了结构体,并且能够从我的代码生成相同的XML
请参阅TestMetaData_Marshal

ValidXML

我为这个示例简化了XML:

<Parent>
	<Name>tic.TEST</Name>
	<MetaData>
		<LawFormID Type="129" DefinedSize="3">DOO</LawFormID>
		<FirmUQ Type="129" DefinedSize="15">BARTOG</FirmUQ>
		<FirmDescription Type="200" DefinedSize="100">Bartog d.o.o. Trebnje</FirmDescription>
	</MetaData>
</Parent>

结构体

我的相应结构体如下。
注意:我为MetaData创建了一个结构体,尽管我更希望不使用结构体(因为json、yaml)。

type Parent struct {
	Name string
	MetaData []Node `xml:"MetaData>any"`
}

type Node struct {
	XMLName     xml.Name // this allows custom node names
	Type        int      `xml:"Type,attr,omitempty"`
	DefinedSize int      `xml:"DefinedSize,attr,omitempty"`
	Text        string   `xml:",chardata"` // required at some places, cannot omit
}

@TestMetadata_Marshal


func TestMetaData_Marshal(t *testing.T) {
	parent := Parent{
		Name: "tic.TEST",
		MetaData: []Node{
			{
				XMLName: xml.Name{
					Local: "LawFormID",
				},
				Text:        "DOO",
				Type:        129,
				DefinedSize: 3,
			}, {
				XMLName: xml.Name{
					Local: "FirmUQ",
				},
				Text:        "BARTOG",
				Type:        129,
				DefinedSize: 15,
			}, {
				XMLName: xml.Name{
					Local: "FirmDescription",
				},
				Text:        "Bartog d.o.o. Trebnje",
				Type:        200,
				DefinedSize: 100,
			},
		}, // \MetaData
	}
	HaveXML := XML(parent)
	fmt.Println(HaveXML)
	if ValidXML != HaveXML {
		t.Error(fmt.Errorf("marshaled XML did not match. Have: %v", HaveXML))
	}
}

Unmarshal

这是问题开始的地方;测试func很简单;结果是MetaData中没有可用的条目。
我尝试了很多不同的tag,还尝试创建了一个自己的MetaData结构体,其中包含Items []Node

func TestUnmarshal() {
	var parent Parent
	err := xml.Unmarshal([]byte(ValidXML), &parent)
	if err != nil {
		fmt.Println(err)
		return
	}
	HaveXML := XML(parent)
	if ValidXML == HaveXML {
		fmt.Println("\tmarshaled XML is Valid")
	} else {
		fmt.Printf("\tmarshaled XML did not match. Have:\n%v\n", HaveXML)
	}
}

go play(将测试转换为'normal' funcs)

https://goplay.tools/snippet/kWS29HR7O9t

问题

在Go中无法实现这个吗?
如果可以实现,我做错了什么?

英文:

Problem

I need to unmarshal XML from an 3rd party application to my GO struct.

what i tried

I created structs and am able to generate identical XML from my code.
@see TestMetaData_Marshal

ValidXML

i simplified the xml for this example:

<Parent>
	<Name>tic.TEST</Name>
	<MetaData>
		<LawFormID Type="129" DefinedSize="3">DOO</LawFormID>
		<FirmUQ Type="129" DefinedSize="15">BARTOG</FirmUQ>
		<FirmDescription Type="200" DefinedSize="100">Bartog d.o.o. Trebnje</FirmDescription>
	</MetaData>
</Parent>

Structs

my corresponding structs are the following.
NOTE: i created a struct for MetaData though i would prefer to NOT use one (due json, yaml)

type Parent struct {
	Name string
	MetaData []Node `xml:"MetaData>any"`
}

type Node struct {
	XMLName     xml.Name // this allows custom node names
	Type        int      `xml:"Type,attr,omitempty"`
	DefinedSize int      `xml:"DefinedSize,attr,omitempty"`
	Text        string   `xml:",chardata"` // required at some places, cannot omit
}

@TestMetadata_Marshal


func TestMetaData_Marshal(t *testing.T) {
	parent := Parent{
		Name: "tic.TEST",
		MetaData: []Node{
			{
				XMLName: xml.Name{
					Local: "LawFormID",
				},
				Text:        "DOO",
				Type:        129,
				DefinedSize: 3,
			}, {
				XMLName: xml.Name{
					Local: "FirmUQ",
				},
				Text:        "BARTOG",
				Type:        129,
				DefinedSize: 15,
			}, {
				XMLName: xml.Name{
					Local: "FirmDescription",
				},
				Text:        "Bartog d.o.o. Trebnje",
				Type:        200,
				DefinedSize: 100,
			},
		}, // \MetaData
	}
	HaveXML := XML(parent)
	fmt.Println(HaveXML)
	if ValidXML != HaveXML {
		t.Error(fmt.Errorf("marshaled XML did not match. Have: %v", HaveXML))
	}
}

Unmarshal

this is where the troubles begin; the test func is trivial; result is that no entries in MetaData are available.
I tried a lot of different tags, also tried creating an own MetaData struct containing Items []Node

func TestUnmarshal() {
	var parent Parent
	err := xml.Unmarshal([]byte(ValidXML), &parent)
	if err != nil {
		fmt.Println(err)
		return
	}
	HaveXML := XML(parent)
	if ValidXML == HaveXML {
		fmt.Println("\tmarshaled XML is Valid")
	} else {
		fmt.Printf("\tmarshaled XML did not match. Have:\n%v\n", HaveXML)
	}
}

go play (turned tests into 'normal' funcs

https://goplay.tools/snippet/kWS29HR7O9t

Question

Is it not possible to do this in go&xml?
Iff it IS possible, what am i doing wrong?

答案1

得分: 3

问题在于any不是标签名,而是一个选项。因此,在使用它时,你必须在它前面加上逗号,例如xml:",any"

我认为你不能将它与>结合使用,所以需要创建一个单独的MetaData结构体:

type Parent struct {
    Name     string
    MetaData MetaData `xml:"MetaData"`
}

type MetaData struct {
    Nodes []Node `xml:",any"`
}

通过这种重构,你的示例将正常工作并输出以下结果(可以在Go Playground上尝试):

=== TestMarshal
<Parent>
    <Name>tic.TEST</Name>
    <MetaData>
        <LawFormID Type="129" DefinedSize="3">DOO</LawFormID>
        <FirmUQ Type="129" DefinedSize="15">BARTOG</FirmUQ>
        <FirmDescription Type="200" DefinedSize="100">Bartog d.o.o. Trebnje</FirmDescription>
    </MetaData>
</Parent>
marshaled XML is Valid
=== TestUnmarshal
marshaled XML is Valid
英文:

The problem is that any is not the tag name, it's an option. So when using it, you have to put a comma before it, e.g. xml:&quot;,any&quot;.

I don't think you can combine it with &gt;, so create a separate MetaData struct:

type Parent struct {
	Name     string
	MetaData MetaData `xml:&quot;MetaData&quot;`
}

type MetaData struct {
	Nodes []Node `xml:&quot;,any&quot;`
}

With this refactoring your example works and outputs (try it on the Go Playground):

=== TestMarshal
&lt;Parent&gt;
	&lt;Name&gt;tic.TEST&lt;/Name&gt;
	&lt;MetaData&gt;
		&lt;LawFormID Type=&quot;129&quot; DefinedSize=&quot;3&quot;&gt;DOO&lt;/LawFormID&gt;
		&lt;FirmUQ Type=&quot;129&quot; DefinedSize=&quot;15&quot;&gt;BARTOG&lt;/FirmUQ&gt;
		&lt;FirmDescription Type=&quot;200&quot; DefinedSize=&quot;100&quot;&gt;Bartog d.o.o. Trebnje&lt;/FirmDescription&gt;
	&lt;/MetaData&gt;
&lt;/Parent&gt;
	marshaled XML is Valid
=== TestUnmarshal
	marshaled XML is Valid

huangapple
  • 本文由 发表于 2022年4月29日 16:52:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/72055299.html
匿名

发表评论

匿名网友

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

确定