使用encoding / xml.Decoder我试图手动解析从http://www.khronos.org/files/collada_schema_1_4加载的XML文件
出于测试目的,我只是迭代文档打印出遇到的任何令牌类型:
func Test (r io.Reader) {
var t xml.Token
var pa *xml.Attr
var a xml.Attr
var co xml.Comment
var cd xml.CharData
var se xml.StartElement
var pi xml.ProcInst
var ee xml.EndElement
var is bool
var xd = xml.NewDecoder(r)
for i := 0; i < 24; i++ {
if t, err = xd.Token(); (err == nil) && (t != nil) {
if a, is = t.(xml.Attr); is { print("ATTR\t"); println(a.Name.Local) }
if pa, is = t.(*xml.Attr); is { print("*ATTR\t"); println(pa) }
if co, is = t.(xml.Comment); is { print("COMNT\t"); println(co) }
if cd, is = t.(xml.CharData); is { print("CDATA\t"); println(cd) }
if pi, is = t.(xml.ProcInst); is { print("PROCI\t"); println(pi.Target) }
if se, is = t.(xml.StartElement); is { print("START\t"); println(se.Name.Local) }
if ee, is = t.(xml.EndElement); is { print("END\t\t"); println(ee.Name.Local) }
}
}
}
现在这是输出:
PROCI xml
CDATA [1/64]0xf84004e050
START schema
CDATA [2/129]0xf84004d090
COMNT [29/129]0xf84004d090
CDATA [2/129]0xf84004d090
START annotation
CDATA [3/129]0xf84004d090
START documentation
CDATA [641/1039]0xf840061000
END documentation
CDATA [2/1039]0xf840061000
END annotation
CDATA [2/1039]0xf840061000
COMNT [37/1039]0xf840061000
CDATA [2/1039]0xf840061000
START import
END import
CDATA [2/1039]0xf840061000
COMNT [14/1039]0xf840061000
CDATA [2/1039]0xf840061000
START element
CDATA [3/1039]0xf840061000
START annotation
请注意,即使在最后一行(第24行)中,在根 xs:schema 元素以及 xs中已经传递了许多属性,也不会输出ATTR或* ATTR行:导入和 xs:element 元素。
这是在Windows 7 64位下的Go 1.0.3 64位。我做错了什么或者我应该提交Go包错误报告吗?
[旁注:在正常的 xml.Unmarshal 中进行正确准备的结构时,xml包捕获并映射已知命名和映射的属性就好了。但是我还需要在根元素中收集“unknown”属性(为这个用例收集命名空间信息,用例为http://github.com/metaleap/go-xsd),因此我尝试使用 Decoder.Token() 即可。
答案 0 :(得分:5)
是的,这种行为是预料之中的。解析属性,但是 不作为xml.Token返回。属性根本不是令牌。 请参阅:http://golang.org/pkg/encoding/xml/#Token
可以通过Attr字段访问这些属性 令牌StartElement。 请参阅:http://golang.org/pkg/encoding/xml/#StartElement
((一些一般提示:
a)不要使用print或println。
b)a,ok:= t。(SomeType)idioma被称为“逗号好”,因为布尔值通常命名为“ok”,而不是“is”。请坚持这些惯例。
c)惯用语类似于
switch t := t.(type) {
case xml.StartElement: ...
case xml.EndElement: ...
}
而不是“if a,is = t。(xml.Attr)...”的列表
d)所有这些“var se xml.StartElement”都是噪音(杂乱)。使用
if se, ok := t.(xml.StartElement); ok { ... }
这将使您的代码更具可读性。 ))