【问题标题】:How do I properly build and nest structs to unmarshal a SOAP response in Go?如何正确构建和嵌套结构以在 Go 中解组 SOAP 响应?
【发布时间】:2021-05-15 15:19:40
【问题描述】:

我在 Go 中使用 encoding/xml 解组 SOAP 响应时遇到问题。 (代码和摘录如下。)

  1. 我用于初始化结构字段的值是否错误? (例如,xml:"xmlns:soap,attr"

我一直在学习的博客文章中的大多数示例不使用带前缀的 XML 字段,例如 <soap:Body>。所以我不完全理解如何用这个包解析那些。

  1. 我的结构嵌套不正确吗?

  2. 我是否需要为每个元素和属性提供结构和字段,以便xml.Unmarshal 正确填充结构?

例如,如果我没有为<soap:Envelope><soap:Body> 提供结构字段,xml.Unmarshal 会忽略这些元素的内容吗?或者我可以只为我想要解组的元素提供结构和字段(例如,只有在 ResData 结构中表示的元素)?

我可能在这里遗漏了一些明显的东西,因为我对 Go 和 SOAP 都很陌生。我并不完全理解 encoding/xml 是如何工作的,即使在阅读了一些展示如何使用它的示例的博客文章并阅读了一些 Go 文档之后也是如此。我可能只是很密集。

这是Go Playground 中的完整测试代码。当我运行它时,我什么也没得到:

[~/d/xml]% ./xmltest
Url:
Name:
Protocol:
Version:
Id:

这是我试图解组的 SOAP 响应:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
      <GetCompanyWsdkUrlResponse xmlns="http://corrigo.com/integration/">
         <GetCompanyWsdkUrlResult xsi:type="GetCompanyWsdkUrlResult">
            <Url>https://am-ce96e.corrigo.com/wsdk/CorrigoService.asmx?wsdl</Url>
            <CompanyName>ACME Test Company</CompanyName>
            <Protocol>HTTPS</Protocol>
            <CompanyVersion>9.6</CompanyVersion>
            <CompanyId>1337</CompanyId>
         </GetCompanyWsdkUrlResult>
      </GetCompanyWsdkUrlResponse>
   </soap:Body>
</soap:Envelope>

这些是我将数据解组到的结构:

type Envelope struct {
    XMLName     xml.Name    `xml:"Envelope"`
    XMLNSs      string      `xml:"xmlns:soap,attr"`
    XMLNSxsi    string      `xml:"xmlns:xsi,attr"`
    XMLNSxsd    string      `xml:"xmlns:xsd,attr"`
    Body
}

type Body struct {
    Body        string      `xml:"Body"`
    Response
}

type Response struct {
    UrlResponse string      `xml:"GetCompanyWsdkUrlResponse"`
    XMLNSs      string      `xml:"xmlns,attr"`
    Result
}

type Result struct {
    UrlResult   string      `xml:"GetCompanyWsdkUrlResult"`
    XMLNSxsi    string      `xml:"xsi:type,attr"`
    ResData
}

type ResData struct {
    Url         string      `xml:"Url"`
    Name        string      `xml:"CompanyName"`
    Protocol    string      `xml:"Protocol"`
    Version     string      `xml:"CompanyVersion"`
    Id          string      `xml:"CompanyId"`
}

【问题讨论】:

    标签: xml go soap unmarshalling


    【解决方案1】:

    (按照问题编号的顺序)

    1。 啊啊啊,你离得太近了!最大的事情是你领导了你不需要的“xsi:”和“xmlns:”。我确实相信 Go 会忽略这些值,然后只查看字段。

    以你的信封结构它应该是这样的(你的其他结构也需要在适当的地方进行调整):

    type Envelope struct {
        XMLName  xml.Name `xml:"Envelope"`
        XMLNSs   string   `xml:"soap,attr"` // Note the lack of `xmlns:`
        XMLNSxsi string   `xml:"xsi,attr"`
        XMLNSxsd string   `xml:"xsd,attr"`
        Body     Body     `xml:"Body"` // Note how we tell go about the body tag here
    }
    

    上面代码块中的body 已经稍微提到了这一点。但是,是的,有很多不同的方法可以做到这一点,但我会发布一个链接去游乐场,在那里你可以找到一系列结构的工作示例,这些结构可以正确解析你提供的 SOAP XML。

    https://play.golang.org/p/L2F4bduac-3

    3。 不,您可以选择仅定义 SOAP 中您需要的内容。假设您只需要公司 ID。你可以制作你的结构:

    type OnlyCompanyID struct {
        XMLName   xml.Name `xml:"Envelope"`
        CompanyID int      `xml:"Body>GetCompanyWsdkUrlResponse>GetCompanyWsdkUrlResult>CompanyId"`
    }
    

    编辑:我强烈建议将我放入游乐场的东西弄乱它。在我看来,Unmarshling XML 比 Go 中的 JSON/YML 等更直接的东西要复杂一些。随意放弃任何后续问题,我可以看到我可以做些什么来解决它们:)

    【讨论】:

    • 哦,我可以只选择我想要解组的内容(RE #3),这真是太棒了。它似乎有点像 XPath。我最初只想使用 XPath,但它的 Go 实现似乎不太好。 RE #1,2:似乎encoding/xml 自动识别前缀,所以我可以省略。超级有用的回应,当我搞砸这些事情时,它会有所帮助。谢谢! :>
    • 实际上还有一个问题:如果我只想使用&gt; 语法选择我想要的字段,我是否需要只为第一个XML 元素提供XMLName 字段/b>?
    • “Another question 实际上”:老实说我不知道​​,但是当我不放 XMLName 时它似乎中断了,在我的 goto 源中也找不到任何有用的注释:@ 987654322@。但我可以 说的是,如果没有 XMLName,它似乎无法工作。 (我在 Go 的日常工作中根本不使用 XML,很遗憾我的经验有限,抱歉)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 2021-03-20
    相关资源
    最近更新 更多