英文:
Reading XML by attribute
问题
尝试使用Golang连接到MS SharePoint,如此处所述,所以我编写了以下代码,返回XML文本:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
const myurl = "https://login.microsoftonline.com/extSTS.srf"
const username = "myuser@mydmain.com"
const password = "mypassword"
const endpoint = "https://mydomain.sharepoint.com/"
const xmlbody = `
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>` + username + `</o:Username>
<o:Password>` + password + `</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>` + endpoint + `</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>`
resp, err := http.Post(myurl, "text/xml", strings.NewReader(xmlbody))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
上述代码能够完美执行第一步,现在我想获取返回的字符串并读取具有ID="Compact0"
的xml
元素,所以我尝试了以下代码:
type Node struct {
XMLName xml.Name
Attrs []xml.Attr `xml:"-"`
Content []byte `xml:",innerxml"`
Nodes []Node `xml:",any"`
}
func walk(nodes []Node, f func(Node) bool) {
for _, n := range nodes {
if f(n) {
walk(n.Nodes, f)
}
}
}
func main() {
// 我的上面的代码,然后是:
var n Node
var data = []byte(body)
buf := bytes.NewBuffer(data)
dec := xml.NewDecoder(buf)
err = dec.Decode(&n)
if err != nil {
panic(err)
}
walk([]Node{n}, func(n Node) bool {
if n.Attrs == "Compact0" { // <= ERROR
fmt.Println(string(n.Content))
}
return true
})
}
但是我得到了以下错误:
cannot convert "Compact0" (untyped string constant) to []xml.AttrcompilerInvalidUntypedConversion
在以下位置:
if n.Attrs == "Compact0" {}
返回的XML
响应是:
<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Header>
<wsa:Action S:mustUnderstand="1" wsu:Id="Action">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</wsa:Action>
<wsa:To S:mustUnderstand="1" wsu:Id="To">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsse:Security S:mustUnderstand="1">
<wsu:Timestamp wsu:Id="TS" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2021-06-30T18:38:50.5911765Z</wsu:Created>
<wsu:Expires>2021-06-30T18:43:50.5911765Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</S:Header>
<S:Body xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<wst:RequestSecurityTokenResponse xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" x
mlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wst:TokenType>urn:passport:compact</wst:TokenType>
<wsp:AppliesTo>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>https://mydomain.sharepoint.com/</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<wst:Lifetime>
<wsu:Created>2021-06-30T18:38:49Z</wsu:Created>
<wsu:Expires>2021-07-01T18:38:49Z</wsu:Expires>
</wst:Lifetime>
<wst:RequestedSecurityToken>
<wsse:BinarySecurityToken Id="Compact0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
t=blablabla==&amp;p=
</wsse:BinarySecurityToken>
</wst:RequestedSecurityToken>
<wst:RequestedAttachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="VkETyJDRdMqocUhjsNftrfT9Z8U="></wsse:Reference>
</wsse:SecurityTokenReference>
</wst:RequestedAttachedReference>
<wst:RequestedUnattachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="VkETyJDRdMqocUhjsNftrfT9Z8U="></wsse:Reference>
</wsse:SecurityTokenReference>
</wst:RequestedUnattachedReference>
</wst:RequestSecurityTokenResponse>
</S:Body>
</S:Envelope>
我需要从中获取以下内容:
<wsse:BinarySecurityToken Id="Compact0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
t=blablabla==&amp;p=
</wsse:BinarySecurityToken>
中的blablabla
。
英文:
Trying to connect to MS sharepoint using Golang as explained here, so I wrote the below that is returning XML text:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
const myurl = "https://login.microsoftonline.com/extSTS.srf"
const username = "myuser@mydmain.com"
const password = "mypassword"
const endpoint = "https://mydomain.sharepoint.com/"
const xmlbody = `
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>` + username + `</o:Username>
<o:Password>` + password + `</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>` + endpoint + `</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>`
resp, err := http.Post(myurl, "text/xml", strings.NewReader(xmlbody))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
The above was able to do the first step perfectly, now I want to fetch the returned string and read the xml
element that had ID="Compact0"
, so I tried this:
type Node struct {
XMLName xml.Name
Attrs []xml.Attr `xml:"-"`
Content []byte `xml:",innerxml"`
Nodes []Node `xml:",any"`
}
func walk(nodes []Node, f func(Node) bool) {
for _, n := range nodes {
if f(n) {
walk(n.Nodes, f)
}
}
}
func main() {
// My code above, followed by:
var n Node
var data = []byte(body)
buf := bytes.NewBuffer(data)
dec := xml.NewDecoder(buf)
err = dec.Decode(&n)
if err != nil {
panic(err)
}
walk([]Node{n}, func(n Node) bool {
if n.Attrs == "Compact0" {. // <= ERROR
fmt.Println(string(n.Content))
}
return true
})
}
But I got this error:
> cannot convert "Compact0" (untyped string constant) to
> []xml.AttrcompilerInvalidUntypedConversion
At:
> if n.Attrs == "Compact0" {}
The returned XML
response is:
<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Header>
<wsa:Action S:mustUnderstand="1" wsu:Id="Action">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</wsa:Action>
<wsa:To S:mustUnderstand="1" wsu:Id="To">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsse:Security S:mustUnderstand="1">
<wsu:Timestamp wsu:Id="TS" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2021-06-30T18:38:50.5911765Z</wsu:Created>
<wsu:Expires>2021-06-30T18:43:50.5911765Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</S:Header>
<S:Body xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<wst:RequestSecurityTokenResponse xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" x
mlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wst:TokenType>urn:passport:compact</wst:TokenType>
<wsp:AppliesTo>
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>https://mydomain.sharepoint.com/</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<wst:Lifetime>
<wsu:Created>2021-06-30T18:38:49Z</wsu:Created>
<wsu:Expires>2021-07-01T18:38:49Z</wsu:Expires>
</wst:Lifetime>
<wst:RequestedSecurityToken>
<wsse:BinarySecurityToken Id="Compact0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
t=blablabla==&amp;p=
</wsse:BinarySecurityToken>
</wst:RequestedSecurityToken>
<wst:RequestedAttachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="VkETyJDRdMqocUhjsNftrfT9Z8U="></wsse:Reference>
</wsse:SecurityTokenReference>
</wst:RequestedAttachedReference>
<wst:RequestedUnattachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="VkETyJDRdMqocUhjsNftrfT9Z8U="></wsse:Reference>
</wsse:SecurityTokenReference>
</wst:RequestedUnattachedReference>
</wst:RequestSecurityTokenResponse>
</S:Body>
</S:Envelope>
From which I need to get the blablabla
at:
<wsse:BinarySecurityToken Id="Compact0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
t=blablabla==&amp;p=
</wsse:BinarySecurityToken>
答案1
得分: 1
使用以下代码:
Attrs []xml.Attr `xml:"-"`
你正在忽略所有属性。你应该这样做:
ID string `xml:"Id,attr"`
然后,检查你要查找的ID。
你得到这个错误是因为n.Attrs
是一个数组。你不能将一个数组与一个字符串值进行比较。
英文:
With:
Attrs []xml.Attr `xml:"-"`
you are ignoring all attributes. You should be able to do:
ID string `xml:"Id,attr"
instead, and check for the ID you are looking for.
You are getting that error because n.Attrs
is an array. You cannot compare an array with a string value.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论