读取 XML 文件的属性

huangapple go评论72阅读模式
英文:

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;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;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 (
	&quot;bytes&quot;
	&quot;encoding/xml&quot;
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;strings&quot;
)

func main() {
	const myurl = &quot;https://login.microsoftonline.com/extSTS.srf&quot;
	const username = &quot;myuser@mydmain.com&quot;
	const password = &quot;mypassword&quot;
	const endpoint = &quot;https://mydomain.sharepoint.com/&quot;
	const xmlbody = `
	&lt;s:Envelope xmlns:s=&quot;http://www.w3.org/2003/05/soap-envelope&quot;
	xmlns:a=&quot;http://www.w3.org/2005/08/addressing&quot;
	xmlns:u=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;&gt;
&lt;s:Header&gt;
  &lt;a:Action s:mustUnderstand=&quot;1&quot;&gt;http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue&lt;/a:Action&gt;
  &lt;a:ReplyTo&gt;
	&lt;a:Address&gt;http://www.w3.org/2005/08/addressing/anonymous&lt;/a:Address&gt;
  &lt;/a:ReplyTo&gt;
  &lt;a:To s:mustUnderstand=&quot;1&quot;&gt;https://login.microsoftonline.com/extSTS.srf&lt;/a:To&gt;
  &lt;o:Security s:mustUnderstand=&quot;1&quot;
	 xmlns:o=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;&gt;
	&lt;o:UsernameToken&gt;
	  &lt;o:Username&gt;` + username + `&lt;/o:Username&gt;
	  &lt;o:Password&gt;` + password + `&lt;/o:Password&gt;
	&lt;/o:UsernameToken&gt;
  &lt;/o:Security&gt;
&lt;/s:Header&gt;
&lt;s:Body&gt;
  &lt;t:RequestSecurityToken xmlns:t=&quot;http://schemas.xmlsoap.org/ws/2005/02/trust&quot;&gt;
	&lt;wsp:AppliesTo xmlns:wsp=&quot;http://schemas.xmlsoap.org/ws/2004/09/policy&quot;&gt;
	  &lt;a:EndpointReference&gt;
		&lt;a:Address&gt;` + endpoint + `&lt;/a:Address&gt;
	  &lt;/a:EndpointReference&gt;
	&lt;/wsp:AppliesTo&gt;
	&lt;t:KeyType&gt;http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey&lt;/t:KeyType&gt;
	&lt;t:RequestType&gt;http://schemas.xmlsoap.org/ws/2005/02/trust/Issue&lt;/t:RequestType&gt;
	&lt;t:TokenType&gt;urn:oasis:names:tc:SAML:1.0:assertion&lt;/t:TokenType&gt;
  &lt;/t:RequestSecurityToken&gt;
&lt;/s:Body&gt;
&lt;/s:Envelope&gt;`

	resp, err := http.Post(myurl, &quot;text/xml&quot;, strings.NewReader(xmlbody))
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(&quot;response Body:&quot;, 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=&quot;Compact0&quot;, so I tried this:

type Node struct {
	XMLName xml.Name
	Attrs   []xml.Attr `xml:&quot;-&quot;`
	Content []byte     `xml:&quot;,innerxml&quot;`
	Nodes   []Node     `xml:&quot;,any&quot;`
}

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(&amp;n)
	if err != nil {
		panic(err)
	}
	walk([]Node{n}, func(n Node) bool {
		if n.Attrs == &quot;Compact0&quot; {.  // &lt;= 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:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;S:Envelope xmlns:wsa=&quot;http://www.w3.org/2005/08/addressing&quot; 
xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot; 
xmlns:wsu=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot; 
xmlns:wsp=&quot;http://schemas.xmlsoap.org/ws/2004/09/policy&quot; 
xmlns:wst=&quot;http://schemas.xmlsoap.org/ws/2005/02/trust&quot; 
xmlns:S=&quot;http://www.w3.org/2003/05/soap-envelope&quot;&gt;
    &lt;S:Header&gt;
        &lt;wsa:Action S:mustUnderstand=&quot;1&quot; wsu:Id=&quot;Action&quot;&gt;http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue&lt;/wsa:Action&gt;
        &lt;wsa:To S:mustUnderstand=&quot;1&quot; wsu:Id=&quot;To&quot;&gt;http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous&lt;/wsa:To&gt;
        &lt;wsse:Security S:mustUnderstand=&quot;1&quot;&gt;
            &lt;wsu:Timestamp wsu:Id=&quot;TS&quot; xmlns:wsu=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;&gt;
            &lt;wsu:Created&gt;2021-06-30T18:38:50.5911765Z&lt;/wsu:Created&gt;
            &lt;wsu:Expires&gt;2021-06-30T18:43:50.5911765Z&lt;/wsu:Expires&gt;
            &lt;/wsu:Timestamp&gt;
        &lt;/wsse:Security&gt;
    &lt;/S:Header&gt;
    &lt;S:Body xmlns:S=&quot;http://www.w3.org/2003/05/soap-envelope&quot;&gt;
        &lt;wst:RequestSecurityTokenResponse xmlns:wsu=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot; x
        mlns:wsp=&quot;http://schemas.xmlsoap.org/ws/2004/09/policy&quot; 
        xmlns:wst=&quot;http://schemas.xmlsoap.org/ws/2005/02/trust&quot;&gt;
            &lt;wst:TokenType&gt;urn:passport:compact&lt;/wst:TokenType&gt;
            &lt;wsp:AppliesTo&gt;
                &lt;wsa:EndpointReference xmlns:wsa=&quot;http://www.w3.org/2005/08/addressing&quot;&gt;
                    &lt;wsa:Address&gt;https://mydomain.sharepoint.com/&lt;/wsa:Address&gt;
                &lt;/wsa:EndpointReference&gt;
            &lt;/wsp:AppliesTo&gt;
            &lt;wst:Lifetime&gt;
                &lt;wsu:Created&gt;2021-06-30T18:38:49Z&lt;/wsu:Created&gt;
                &lt;wsu:Expires&gt;2021-07-01T18:38:49Z&lt;/wsu:Expires&gt;
            &lt;/wst:Lifetime&gt;
            &lt;wst:RequestedSecurityToken&gt;
                &lt;wsse:BinarySecurityToken Id=&quot;Compact0&quot; 
                xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;&gt;
                t=blablabla==&amp;amp;p=
                &lt;/wsse:BinarySecurityToken&gt;
            &lt;/wst:RequestedSecurityToken&gt;
            &lt;wst:RequestedAttachedReference&gt;
                &lt;wsse:SecurityTokenReference xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;&gt;
                    &lt;wsse:Reference URI=&quot;VkETyJDRdMqocUhjsNftrfT9Z8U=&quot;&gt;&lt;/wsse:Reference&gt;
                &lt;/wsse:SecurityTokenReference&gt;
            &lt;/wst:RequestedAttachedReference&gt;
            &lt;wst:RequestedUnattachedReference&gt;
                &lt;wsse:SecurityTokenReference xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;&gt;
                    &lt;wsse:Reference URI=&quot;VkETyJDRdMqocUhjsNftrfT9Z8U=&quot;&gt;&lt;/wsse:Reference&gt;
                &lt;/wsse:SecurityTokenReference&gt;
            &lt;/wst:RequestedUnattachedReference&gt;
        &lt;/wst:RequestSecurityTokenResponse&gt;
    &lt;/S:Body&gt;
&lt;/S:Envelope&gt;

From which I need to get the blablabla at:

                &lt;wsse:BinarySecurityToken Id=&quot;Compact0&quot; 
                xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;&gt;
                t=blablabla==&amp;amp;p=
                &lt;/wsse:BinarySecurityToken&gt;

答案1

得分: 1

使用以下代码:

    Attrs   []xml.Attr `xml:"-"`

你正在忽略所有属性。你应该这样做:

   ID string `xml:"Id,attr"`

然后,检查你要查找的ID。

你得到这个错误是因为n.Attrs是一个数组。你不能将一个数组与一个字符串值进行比较。

英文:

With:

    Attrs   []xml.Attr `xml:&quot;-&quot;`

you are ignoring all attributes. You should be able to do:

   ID string `xml:&quot;Id,attr&quot;

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.

huangapple
  • 本文由 发表于 2021年7月1日 03:29:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/68200638.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定