使用命名空间

时间:2018-02-07 18:53:34

标签: xml go xmpp

我希望使用github.com/mattn/go-xmpp Golang包对XMPP用户进行操作。我改变了一个小官员example并得到了类似的东西:

switch v := chat.(type) {
case xmpp.IQ:
    if len(v.Query) != 0 {
        fmt.Printf("Query: %s", v.Query)
    }
default:
    fmt.Printf("detect default type: %T\n", v)
}

v.Query是一个XML文档,其名称空间如

<query xmlns="jabber:iq:roster">
<item jid="JID1" name="Name" subscription="none" ask="subscribe">
    <group></group>
</item>
<item jid="JID2" name="Another name" subscription="both">
    <group>Group</group>
</item>
<item jid="JID3" name="Eman" subscription="both">
    <group>AnotherGroup</group>
</item>
</query>

如何解析此文档并迭代jid个元素?

1 个答案:

答案 0 :(得分:0)

标准库中有两种解析XML文档的机制,一种是流传输机制,另一种是基于结构的机制。


流API

使用流传输机制会有点冗长,但对于大型文档(例如大型花名册)也非常有效。基本思想是创建一个解码器,遍历令牌并提取所需的数据。在这种情况下,您只需要仅在起始元素上的JID属性,因此您还需要遍历每个起始元素的属性以找到一个名为“ jid”的属性。以下是执行此操作的最小示例,对于真实项目,您可能还需要验证每个起始元素是否为“ item”:

func main() {
    d := xml.NewDecoder(strings.NewReader(v.Query))
    var jids []string
    for {
        tok, err := d.Token()
        if err != nil && err != io.EOF {
            panic(err)
        }
        if tok == nil {
            break
        }
        start, ok := tok.(xml.StartElement)
        if !ok {
            // We'll skip anything that's not a start element in this example.
            continue
        }

        jid := getAttr("jid", start.Attr)
        if jid != "" {
            jids = append(jids, jid)
        }
    }

    fmt.Println(jids)
}

func getAttr(name string, attr []xml.Attr) string {
    for _, a := range attr {
        if a.Name.Local == name {
            return a.Value
        }
    }
    return ""
}

您可以在以下操场上运行此示例:https://play.golang.org/p/s6flTADDsnT


基于结构的API

基于结构的API稍微容易一些,但对于庞大的名册而言,效率可能较低。我们将创建一个表示有效负载的结构,将数据解组到其中,然后遍历它并取出JID,而不是逐个令牌地流化XML有效负载令牌。表示名册响应的结构如下所示:

type rosterResponse struct {
    XMLName xml.Name `xml:"jabber:iq:roster query"`
    Items   []struct {
        JID string `xml:"jid,attr"`
    } `xml:"item"`
}

可以在此处找到拆封示例:

https://play.golang.org/p/g2qLUkdZ7qt

为了更好地理解这两个示例中发生的情况,我强烈建议您阅读encoding/xml的软件包级别的文档,其中涵盖了所有这些内容以及许多有用的信息!