如何使用Go获取XML中指定的结构?

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

How to get structure specified in XML with Go?

问题

我有一个名为test.xml的XML文件,内容如下:

<metalib tagsetversion="1" name="TLog" version="1">
  <struct name="STRUCT_1">
    <entry name="ENTRY_1"/>
  </struct>

  <struct name="STRUCT_2">
    <entry name="ENTRY_1"/>
    <entry name="ENTRY_2"/>
  </struct>

   <!-- 其他结构体 -->

  <union name="UNION" version="1">
    <entry type="STRUCT_1"       id="ID_STRUCT_1" />
    <entry type="STRUCT_2"       id="ID_STRUCT_2" />
  </union>
</metalib>

我想要将其解析为以下结构体:

map["STRUCT_1"] == ["ENTRY_1"],map["STRUCT_2"] == ["ENTRY_1","ENTRY_2"]

还有另一个映射:

map2["ID_STRUCT_1"] == "STRUCT_1",map2["ID_STRUCT_2"] == "STRUCT_2"

我尝试使用github.com/clbanning/mxj/x2j来解决这个问题,我的代码如下:

package main

import (
	"encoding/json"
	"os"
	"fmt"
	"testing"

	"github.com/clbanning/mxj/x2j"
)

func TestXml2Map(t *testing.T) {
	filePath := "test.xml"
	fi, fierr := os.Stat(filePath)
	if fierr != nil {
		fmt.Println("fierr:", fierr.Error())
		return
	}
	fh, fherr := os.Open(filePath)
	if fherr != nil {
		fmt.Println("fherr:", fherr.Error())
		return
	}
	defer fh.Close()
	buf := make([]byte, fi.Size())
	_, nerr := fh.Read(buf)
	if nerr != nil {
		fmt.Println("nerr:", nerr.Error())
		return
	}
	mmap, merr := x2j.XmlToMap(buf)
	if merr != nil {
		fmt.Println("merr:", merr.Error())
		return
	}
	// fmt.Println("mmap:", mmap)
	metalib := mmap["metalib"]
	// fmt.Println("metalib:", metalib)

	json.Unmarshal(buf, &metalib)
	mapmetalib := metalib.(map[string]interface{})
	// fmt.Println("mapmetalib struct: ", mapmetalib["struct"])

	istruct := mapmetalib["struct"]
	json.Unmarshal(buf, &istruct)
	mapstruct := istruct.([]interface{})
	fmt.Println("mapstruct: ", mapstruct)
}

但我感到困惑,不知道下一步该怎么做。

英文:

I have an XML file like this test.xml

&lt;metalib tagsetversion=&quot;1&quot; name=&quot;TLog&quot; version=&quot;1&quot;&gt;
  &lt;struct name=&quot;STRUCT_1&quot;&gt;
    &lt;entry name=&quot;ENTRY_1&quot;/&gt;
  &lt;/struct&gt;

  &lt;struct name=&quot;STRUCT_2&quot;&gt;
    &lt;entry name=&quot;ENTRY_1&quot;/&gt;
    &lt;entry name=&quot;ENTRY_2&quot;/&gt;
  &lt;/struct&gt;

   &lt;!-- many structs --&gt;

  &lt;union name=&quot;UNION&quot; version=&quot;1&quot;&gt;
    &lt;entry type=&quot;STRUCT_1&quot;       id=&quot;ID_STRUCT_1&quot; /&gt;
    &lt;entry type=&quot;STRUCT_2&quot;       id=&quot;ID_STRUCT_2&quot; /&gt;
  &lt;/union&gt;
&lt;/metalib&gt;

And I want parse it to go struct like this:

map[&quot;STRUCT_1&quot;] == [&quot;ENTRY_1&quot;], map[&quot;STRUCT_2&quot;] == [&quot;ENTRY_1&quot;,&quot;ENTRY_2&quot;]

and another map:

map2[&quot;ID_STRUCT_1&quot;] == &quot;STRUCT_1&quot;, map2[&quot;ID_STRUCT_2&quot;] == &quot;STRUCT_2&quot;

I have tried to use github.com/clbanning/mxj/x2j slove this problem, and my code like this:

package main

import (
	&quot;encoding/json&quot;
	&quot;os&quot;
	&quot;fmt&quot;
	&quot;testing&quot;

	&quot;github.com/clbanning/mxj/x2j&quot;
)

func TestXml2Map(t *testing.T) {
	filePath := &quot;test.xml&quot;
	fi, fierr := os.Stat(filePath)
	if fierr != nil {
		fmt.Println(&quot;fierr:&quot;, fierr.Error())
		return
	}
	fh, fherr := os.Open(filePath)
	if fherr != nil {
		fmt.Println(&quot;fherr:&quot;, fherr.Error())
		return
	}
	defer fh.Close()
	buf := make([]byte, fi.Size())
	_, nerr := fh.Read(buf)
	if nerr != nil {
		fmt.Println(&quot;nerr:&quot;, nerr.Error())
		return
	}
	mmap, merr := x2j.XmlToMap(buf)
	if merr != nil {
		fmt.Println(&quot;merr:&quot;, merr.Error())
		return
	}
	// fmt.Println(&quot;mmap:&quot;, mmap)
	metalib := mmap[&quot;metalib&quot;]
	// fmt.Println(&quot;metalib:&quot;, metalib)

	json.Unmarshal(buf, &amp;metalib)
	mapmetalib := metalib.(map[string]interface{})
	// fmt.Println(&quot;mapmetalib struct: &quot;, mapmetalib[&quot;struct&quot;])

	istruct := mapmetalib[&quot;struct&quot;]
	json.Unmarshal(buf, &amp;istruct)
	mapstruct := istruct.([]interface{})
	fmt.Println(&quot;mapstruct: &quot;, mapstruct)
}

But I am confused and don't know how to do next step.

答案1

得分: 1

package main

import (
	"encoding/xml"
	"fmt"
)

type entry struct {
	Name string `xml:"name,attr"`
}
type Struct struct {
	Name  string  `xml:"name,attr"`
	Entry []entry `xml:"entry"`
}
type metalib struct {
	XMLName xml.Name `xml:"metalib"`
	Struct  []Struct `xml:"struct"`
}

func main() {
	datastr := []byte(`<metalib tagsetversion="1" name="TLog" version="1">
		<struct name="STRUCT_1">
			<entry name="ENTRY_1"/>
		</struct>

		<struct name="STRUCT_2">
			<entry name="ENTRY_1"/>
			<entry name="ENTRY_2"/>
		</struct>

		<!-- many structs -->

		<union name="UNION" version="1">
		<entry type="STRUCT_1"       id="ID_STRUCT_1" />
		<entry type="STRUCT_2"       id="ID_STRUCT_2" />
		</union>
		</metalib>`)
	metalib := metalib{}
	err := xml.Unmarshal(datastr, &metalib)
	if err != nil {
		return
	}
	fmt.Printf("%v\n", metalib)

}
英文:
package main
import (
&quot;encoding/xml&quot;
&quot;fmt&quot;
)
type entry struct {
Name string `xml:&quot;name,attr&quot;`
}
type Struct struct {
Name  string  `xml:&quot;name,attr&quot;`
Entry []entry `xml:&quot;entry&quot;`
}
type metalib struct {
XMLName xml.Name `xml:&quot;metalib&quot;`
Struct  []Struct `xml:&quot;struct&quot;`
}
func main() {
datastr := []byte(`&lt;metalib tagsetversion=&quot;1&quot; name=&quot;TLog&quot; version=&quot;1&quot;&gt;
&lt;struct name=&quot;STRUCT_1&quot;&gt;
&lt;entry name=&quot;ENTRY_1&quot;/&gt;
&lt;/struct&gt;
&lt;struct name=&quot;STRUCT_2&quot;&gt;
&lt;entry name=&quot;ENTRY_1&quot;/&gt;
&lt;entry name=&quot;ENTRY_2&quot;/&gt;
&lt;/struct&gt;
&lt;!-- many structs --&gt;
&lt;union name=&quot;UNION&quot; version=&quot;1&quot;&gt;
&lt;entry type=&quot;STRUCT_1&quot;       id=&quot;ID_STRUCT_1&quot; /&gt;
&lt;entry type=&quot;STRUCT_2&quot;       id=&quot;ID_STRUCT_2&quot; /&gt;
&lt;/union&gt;
&lt;/metalib&gt;`)
metalib := metalib{}
err := xml.Unmarshal(datastr, &amp;metalib)
if err != nil {
return
}
fmt.Printf(&quot;%v\n&quot;, metalib)
}

huangapple
  • 本文由 发表于 2022年8月9日 19:05:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/73290795.html
匿名

发表评论

匿名网友

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

确定