无法使用:in标记解析GO中的xml

时间:2016-01-15 21:57:29

标签: xml go

我发现如果XML文件中的标签中包含Summary,则Go中的解组代码似乎不起作用。任何见解?

例如,在下面的XML文件中,Cevent有效但<summary>...AIR QUALITY ALERT </summary> <cap:event>Air Quality Alert</cap:event> 无效。

type Entry struct{
    Summary    string   `xml:"summary"`
    Cevent     string   `xml:"cap:event"`
}
  scope :search_stuff, lambda { |search|
    search_conditions = Array.new(4, "%#{search}%")
    {
      :include => {:sponsor => [], :routing_form_pi_users => [:user], :item => []},
      :conditions => ["id like ? or title like ? or users.name like ? or sponsors.name like ?", *search_conditions]
    }
  }

3 个答案:

答案 0 :(得分:4)

cap是名称空间标识符,不是标记名称的一部分。这是urn:oasis:names:tc:emergency:cap:1.1

的简写

(这个答案看起来可能对命名空间有一个很好的浓缩解释:What does "xmlns" in XML mean?

Go&#34; encoding / xml&#34; package不能很好地处理命名空间,但是如果没有冲突的标记,你可以完全忽略命名空间

type Entry struct {
    Summary string `xml:"summary"`
    Event   string `xml:"event"`
}

指定事件的正确方法,特别是在不同命名空间中相同标记的情况下,将使用完整的命名空间,如:

type Entry struct {
    Summary string `xml:"summary"`
    Event   string `xml:"urn:oasis:names:tc:emergency:cap:1.1 event"`
}

以下是一个工作示例:https://play.golang.org/p/ry55F2pWKY

答案 1 :(得分:3)

cap不是标记名称的一部分,而是名称空间标识符(urn:oasis:names:tc:emergency:cap:1.1的缩写,正如您在评论中提供的那样)。这是正确的表示法:

type Entry struct{
    Summary    string   `xml:"summary"`
    Cevent     string   `xml:"urn:oasis:names:tc:emergency:cap:1.1:cap event"`
}

注意空格而不是:来表示命名空间。另请注意,仅使用命名空间标识符(如xml:"cap event"不起作用

工作示例(https://play.golang.org/p/rjkb2esGgv):

package main

import "fmt"
import "encoding/xml"

type Entry struct{
    Summary    string   `xml:"summary"`
    Cevent     string   `xml:"urn:oasis:names:tc:emergency:cap:1.1:cap event"`
}

func main() {
    xmlString := []byte(`
        <doc xmlns:cap = 'urn:oasis:names:tc:emergency:cap:1.1'>
            <summary>...AIR QUALITY ALERT </summary>
            <cap:event>Air Quality Alert</cap:event>
        </doc>
    `)
    entry := new(Entry)

    if err := xml.Unmarshal(xmlString, entry); err == nil {
        fmt.Println(entry)
    } 
}

答案 2 :(得分:0)

你只需要逃脱冒号。因此,将您的xml标记更改为xml:"cap\:event",它将按预期工作。

type Entry struct{
    Summary    string   `xml:"summary"`
    Cevent     string   `xml:"cap\:event"`
}

使用带有微小修改的unmarshal示例在xml页面上对此进行了测试;

package main

import (
    "encoding/xml"
    "fmt"
)

func main() {
    type Email struct {
        Where string `xml:"where,attr"`
        Addr  string
    }
    type Address struct {
        City, State string
    }
    type Result struct {
        XMLName xml.Name `xml:"Person"`
        Name    string   `xml:"Full\:Name"`
        Phone   string
        Email   []Email
        Groups  []string `xml:"Group>Value"`
        Address
    }
    v := Result{Name: "none", Phone: "none"}

    data := `
        <Person>
            <Full:Name>Grace R. Emlin</Full:Name>
            <Company>Example Inc.</Company>
            <Email where="home">
                <Addr>gre@example.com</Addr>
            </Email>
            <Email where='work'>
                <Addr>gre@work.com</Addr>
            </Email>
            <Group>
                <Value>Friends</Value>
                <Value>Squash</Value>
            </Group>
            <City>Hanga Roa</City>
            <State>Easter Island</State>
        </Person>
    `
    err := xml.Unmarshal([]byte(data), &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    fmt.Printf("XMLName: %#v\n", v.XMLName)
    fmt.Printf("Name: %q\n", v.Name)
    fmt.Printf("Phone: %q\n", v.Phone)
    fmt.Printf("Email: %v\n", v.Email)
    fmt.Printf("Groups: %v\n", v.Groups)
    fmt.Printf("Address: %v\n", v.Address)
}

删除转义符,它将为Name打印“none”。使用空格代替:\:,它也可以使用。 xml中的空格会导致解析错误,因为它显然无效。