4

如果在 Go 中使用 XML,我正在尝试解析一块:

package main

import (
    "encoding/xml"
    "fmt"
)

type XML struct {
    Foo string `xml:"foo"`
}

func main() {
    rawXML := []byte(`
<xml>
  <foo>A</foo>
  <ns:foo>B</ns:foo>
</xml>`)

    x := new(XML)
    xml.Unmarshal(rawXML, x)
    fmt.Printf("foo: %s\n", x.Foo)
}

这输出:

foo: B

虽然我预计它会产生:

foo: A

如何获取第一个foo标签的内容(即没有命名空间的标签)?

4

3 回答 3

8

我不认为 xml 解码器可以指定一个元素不应该有带有结构标签的命名空间。但我确实知道它可以为您检索有关命名空间的信息,然后您可以在后处理数据以获得相同的结果:

package main

import (
    "encoding/xml"
    "fmt"
)

type Foo struct {
    XMLName xml.Name
    Data string `xml:",chardata"`
}

type XML struct {
    Foo []Foo `xml:"foo"`
}

func main() {
    rawXML := []byte(`
<xml>
  <foo>A</foo>
  <ns:foo>B</ns:foo>
</xml>`)

    x := new(XML)
    xml.Unmarshal(rawXML, x)
    //fmt.Printf("foo: %#v\n", x)
    for _, el := range x.Foo {
       if el.XMLName.Space == "" {
          fmt.Printf("non namespaced foo %q", el.Data)
      }
    }
}

http://play.golang.org/p/aDEFPmHPc0

于 2013-01-04T07:18:45.790 回答
4

您的 xml 文档中有两个串联的值。您的结构中只有一个值的空间。xml 解析器正在解析第一个,然后用第二个覆盖它。

将 Foo 更改为结构中的切片,然后您将获得这两个值。

http://play.golang.org/p/BRgsuMQ7rK

package main

import (
    "encoding/xml"
    "fmt"
)

type XML struct {
    Foo []string `xml:"foo"`
}

func main() {
    rawXML := []byte(`
<xml>
  <foo>A</foo>
  <ns:foo>B</ns:foo>
</xml>`)

    x := new(XML)
    xml.Unmarshal(rawXML, x)
    fmt.Printf("foo: %s\n", x.Foo[0])
    fmt.Printf("both: %v\n", x.Foo)
}
于 2013-01-03T19:44:44.720 回答
0

选择xml:"foo"器语法采用可选的命名空间xml:"ns foo",但问题是它不支持选择无命名空间的方法。

一种修复方法是简单地将命名空间分配给您现在可以使用语法xml.Decoder.DefaultSpace选择的非命名空间标签:xml:"<ns> <tag>"

https://play.golang.org/p/1UggvqLFT9x

import (
    "encoding/xml"
    "strings"
    "fmt"
)

type Doc struct {
    Foo string `xml:"_ foo"` // <-- <foo> will now be <_:foo>
    NsFoo string `xml:"ns foo"`
}

var input = `<xml>
  <foo>A</foo>
  <ns:foo>B</ns:foo>
</xml>`

func main() {
    decoder := xml.NewDecoder(strings.NewReader(input))
    decoder.DefaultSpace = "_"

    doc := &Doc{}
    decoder.Decode(doc)

    fmt.Printf("<foo>: %#v\n", doc.Foo)
    fmt.Printf("<ns:foo>: %#v\n", doc.NsFoo)

}

印刷:

<foo>: A
<ns:foo>: B
于 2020-06-11T06:21:32.700 回答