2017-08-02 591 views
2

我剛開始學習Go。我想解析一個SOAP服務。我無法解析XML。這裏的XML:在Go中解析SOAP

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 

    <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
     <wsse:UsernameToken> 
     <wsse:Username>USERNAME</wsse:Username> 
     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">SECRET</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
    </SOAP-ENV:Header> 

    <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" EchoToken="abc123" Version="1.0" TimeStamp="2005-08-01T09:30:47+08:00"> 
     <AvailStatusMessages HotelCode="HOTEL"> 
     <AvailStatusMessage BookingLimit="10"> 
      <StatusApplicationControl Start="2010-01-01" End="2010-01-14" InvTypeCode="A1K" RatePlanCode="GLD"/> 
     </AvailStatusMessage> 
     </AvailStatusMessages> 
    </OTA_HotelAvailNotifRQ> 
    </SOAP-ENV:Body> 

</SOAP-ENV:Envelope> 

這裏是我寫來解析XML代碼:

package main 

import (
    "fmt" 
    "encoding/xml" 
) 

type Envelope struct { 
    XMLName xml.Name 
    SOAPENV string `xml:"xmlns:SOAP-ENV,attr"` 
    XSD  string `xml:"xmlns:xsd,attr"` 
    XSI  string `xml:"xmlns:xsi,attr"` 
    SOAPENC string `xml:"xmlns:SOAP-ENC,attr"` 
    NS9132 string `xml:"xmlns:ns9132,attr"` 
    Header Header `xml:"SOAP-ENV:Header"` 
} 

type Header struct { 
    XMLName xml.Name `xml:"SOAP-ENV:Header"` 
    Security Security `xml:"wsse:Security"` 
} 

type Security struct { 
    XMLName  xml.Name `xml:"wsse:Security"` 
    MustUnderstand string `xml:"soap:mustUnderstand,attr"` 
    WSSE   string `xml:"xmlns:wsse,attr"` 
    SOAP   string `xml:"xmlns:soap,attr"` 
    UsernameToken struct { 
     XMLName xml.Name `xml:"wsse:UsernameToken"` 
     Username string `xml:"wsse:Username"` 
     Password string `xml:"wsse:Password"` 
    } 
} 

func main() { 

    Soap := []byte(`<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 

    <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
     <wsse:UsernameToken> 
     <wsse:Username>USERNAME</wsse:Username> 
     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">SECRET</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
    </SOAP-ENV:Header> 

    <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" EchoToken="abc123" Version="1.0" TimeStamp="2005-08-01T09:30:47+08:00"> 
     <AvailStatusMessages HotelCode="HOTEL"> 
     <AvailStatusMessage BookingLimit="10"> 
      <StatusApplicationControl Start="2010-01-01" End="2010-01-14" InvTypeCode="A1K" RatePlanCode="GLD"/> 
     </AvailStatusMessage> 
     </AvailStatusMessages> 
    </OTA_HotelAvailNotifRQ> 
    </SOAP-ENV:Body> 

</SOAP-ENV:Envelope>`) 

    res := &Envelope{} 
    err := xml.Unmarshal(Soap, res) 

    fmt.Println(res.Header.Security.UsernameToken.Username, err) 
} 

爲什麼返回nil。我期望從它獲得用戶名值。另外爲什麼我不能在Envelo結構上使用xml:"SOAP-ENV:Envelope"作爲XMLName?該錯誤消息是expected element type <SOAP-ENV:Envelope> but have <Envelope>

我去的版本是1.8.3

回答

4

只需使用xml:"UsernameToken"代替xml:"wsse:UsernameToken"xml:"wsse:Security" - >xml:"Security"

package main 

import (
    "fmt" 
    "encoding/xml" 
) 

type Envelope struct { 
    XMLName xml.Name 
    Header Header 
} 

type Header struct { 
    XMLName xml.Name `xml:"Header"` 
    Security Security `xml:"Security"` 
} 

type Security struct { 
    XMLName  xml.Name `xml:"Security"` 
    MustUnderstand string `xml:"mustUnderstand,attr"` 
    WSSE   string `xml:"wsse,attr"` 
    SOAP   string `xml:"soap,attr"` 
    UsernameToken struct { 
     XMLName xml.Name `xml:"UsernameToken"` 
     Username string `xml:"Username"` 
     Password string `xml:"Password"` 
    } 
} 

func main() { 

    Soap := []byte(`<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 

    <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
     <wsse:UsernameToken> 
     <wsse:Username>USERNAME</wsse:Username> 
     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">SECRET</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
    </SOAP-ENV:Header> 

    <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" EchoToken="abc123" Version="1.0" TimeStamp="2005-08-01T09:30:47+08:00"> 
     <AvailStatusMessages HotelCode="HOTEL"> 
     <AvailStatusMessage BookingLimit="10"> 
      <StatusApplicationControl Start="2010-01-01" End="2010-01-14" InvTypeCode="A1K" RatePlanCode="GLD"/> 
     </AvailStatusMessage> 
     </AvailStatusMessages> 
    </OTA_HotelAvailNotifRQ> 
    </SOAP-ENV:Body> 

</SOAP-ENV:Envelope>`) 

    res := &Envelope{} 
    err := xml.Unmarshal(Soap, res) 

    fmt.Println(res.Header.Security.UsernameToken.Username, err) 
} 

輸出:USERNAME <nil>

+0

它的作品。有沒有解釋爲什麼我可以省略'wsse:'部分? – otezz

+1

@otezz:'wsse:'是一個[名稱空間前綴](https://en.wikipedia.org/wiki/XML_namespace),它不是元素名稱的一部分。 – JimB

+0

@JimB現在我明白了。謝謝。 – otezz