使用命名空间迭代 xml 中的元素
Posted
技术标签:
【中文标题】使用命名空间迭代 xml 中的元素【英文标题】:Iterate over elements in xml with namespace 【发布时间】:2018-02-07 18:53:33 【问题描述】:我想用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
元素?
【问题讨论】:
你有没有尝试过?例如,thexml
package?
当然我试过了,但是所有的例子都是xml
包文档没有说明命名空间。
此answer 可能对您的情况有所帮助。
【参考方案1】:
标准库中有两种解析XML文档的机制,一种是流式机制,一种是基于结构的机制。
流式 API
使用流式传输机制会有点冗长,但对于大型文档(例如大型花名册)也非常有效。基本思想是创建一个解码器,遍历令牌并提取您需要的数据。在这种情况下,您只需要仅在开始元素上的 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 有效负载令牌。代表名册响应的结构如下所示:
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 中的元素的主要内容,如果未能解决你的问题,请参考以下文章