为什么Go的encoding/xml.Decoder.Token()不会产生xml.Attr标记呢?

met*_*eap 0 xml xsd xml-attribute go xml-parsing

使用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) }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在这是输出:

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
Run Code Online (Sandbox Code Playgroud)

请注意,即使在最后一行(第24行)中,在根xs:schema元素以及xs:importxs:element元素中传递了许多属性,也不会输出ATTR或*ATTR行.

这是在Windows 7 64位下的Go 1.0.3 64位.我做错了什么或者我应该提交Go包错误报告吗?

[ 旁注:当正常的xml.Unmarshal进入正确准备的结构时,xml包捕获并映射已知命名和映射的属性就好了.但是我还需要在根元素中收集"unknown"属性(收集这个用例的命名空间信息,用例是http://github.com/metaleap/go-xsd),因此我尝试使用Decoder.Token().]

Vol*_*ker 5

是的,这种行为是预期的.解析属性,但不作为xml.Token返回.属性根本不是令牌.请参阅:http://golang.org/pkg/encoding/xml/#Token

可以通过Token StartElement中的Attr字段访问这些属性.请参阅:http://golang.org/pkg/encoding/xml/#StartElement

((一些一般提示:

a)不要使用print或println.

b)a,ok:= t.(SomeType)idioma被称为"逗号okay",因为布尔值通常命名为"ok",而不是"is".请坚持这些惯例.

c)惯用语就像

switch t := t.(type) {
  case xml.StartElement: ...
  case xml.EndElement: ...
}
Run Code Online (Sandbox Code Playgroud)

而不是你的列表"if a,is = t.(xml.Attr)......"

d)所有这些"var se xml.StartElement"都是噪音(杂乱).使用

if se, ok := t.(xml.StartElement); ok { ... }
Run Code Online (Sandbox Code Playgroud)

这将使您的代码更具可读性.))