xml - 使用命名空间迭代 xml 中的元素

标签 xml go xmpp

我想用 XMPP 用户操作 github.com/mattn/go-xmpp Golang 包。我换个小官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元素?

最佳答案

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

流媒体 API

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

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

基于 struct 的 API 更容易一些,但对于大型名册也可能效率较低。我们将创建一个表示有效负载的结构,将数据解码到其中,然后对其进行迭代并提取 JID,而不是逐个标记流式传输 XML 有效负载 token 。代表名册响应的结构如下所示:
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 的包级文档。 ,它涵盖了所有这些以及更多有用的信息!

关于xml - 使用命名空间迭代 xml 中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48671268/

相关文章:

ios - XMPPFramework - 在 iOS 中未收到存在

ruby-on-rails - 动态生成 XML 并将其发布到 Rails 中的 Web 服务

javascript - 如何在 Ejabberd 中启用基于角色的用户聊天

c# - C#读取特定的XML数据

pointers - 转到错误 : "embedded type cannot be a pointer to interface"

json - 在 Go 中支持动态结构字段的干净解决方案是什么?

json - 在 golang 中解码顶级 json 对象

java - Smack 异常 - 由我的 Java 安装或 Smack 引起

xml - 使用通配符的 XPath-Query 不起作用

java - xml中textview前后的空白