Go中解析具有多个命名空间的嵌套XML的方法

407 阅读2分钟

我想从一个嵌套的XML中解析出一个子集的值。我希望不必引入任何依赖性,只需使用标准库中的xml包。

完整的例子是嵌套的,有几个不同的命名空间在起作用。我看到有一些关于xml命名空间的公开问题,所以我做了一个小的MWE,其中有我认为是最小级别的命名空间,对于我试图提取的东西来说,它成功了。

小例子 - Go Playground

...
//abbreviated, see go playground link for full data structure

	reader := strings.NewReader(dat1)
	decoder := xml.NewDecoder(reader)

	//https://stackoverflow.com/questions/59615418/how-to-parse-xml-in-slice-format
	type StuffList struct {
		Stuff []string `xml:"SubLevel1>SubLevel2"`
	}

	var sl StuffList

	err := decoder.Decode(&sl)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("rl:", sl.Stuff)

有了这个例子,我试着把它应用到有更多层次的嵌套和命名空间的完整文档中,它返回了一个空的切片。

完整的例子--Go Playground链接

  1. 我可以用Decode 来阅读这个文件吗?不知道Decode 和需要调用Unmarshall 之间的界限在哪里?我是否需要在结构标签中增加一些细节,以便能够正确 "看到 "树?我曾尝试增加一到两层,但没有成功。

  2. 什么时候需要结构的结构,而不是仅仅读入一个片断?我认为在标签中指定适当的标签路径,基本上可以避免我为整棵树创建结构?

  3. 有什么方法可以反省较小的MWE在哪些地方有效,较大的例子在哪些地方失败?我不太明白这两者之间发生了什么。我尝试了一下delve 包,但没有得到任何有用的东西。

在您将SubLevel1和SubLevel2嵌入到额外的层中后,您的Stuff 结构中的路径必须变得更长,才能 "到达 "该层中。我改变了。

type StuffList struct {
		Stuff []string `xml:"SubLevel1>SubLevel2"`
	}

type StuffList struct {
		Stuff []string `xml:"Response2>TopLevel>SubLevel1>SubLevel2"`
	}

然后就成功了。Go Playground - Go编程语言

所以,为了回答你的问题。

  1. 是的:smiley:

  2. 当您需要从XML的更多层次获取更多信息时,我建议添加结构层和/或结构片。如果您所寻找的只是来自特定 XPath 的信息,那么您现在的情况就很好。如果您不仅需要多个 XPath,还需要知道哪个 SubLevel2 对应于哪个 SubLevel1,那么您可能需要定义一个SubLevel1 结构片,每个结构片都包含 SubLevel2 值的字符串片。

  3. 我不确定是否有办法做到这一点。我刚才滚动了一下,发现你第二个例子中的层嵌套得更深,但路径是一样的,所以我开始添加前缀,"TopLevel",然后是 "Response2",直到它返回值。我不知道是否有办法进行调试。