jjzjj

xml - 在 go 中解码特定的 SOAP 响应

coder 2024-07-09 原文

我正在尝试使用以下结构解码以下 SOAP 响应。

var data = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3rg/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <doSendResponse>
            <doSendResult>Send OK.&lt;ReturnIDs&gt;c71cf425f5;e5e4dbb5ca&lt;/ReturnIDs&gt;</doSendResult>
        </doSendResponse>
    </soap:Body>
</soap:Envelope>`

type ResponseBody struct {
    ResponseBody SendResponse `xml:"Body"`
}
type SendResponse struct {
    Result Result `xml:"doSendResponse"`
}
type Result struct {
    RawMessage string `xml:"doSendResult"`
}

一切顺利,直到 <doSendResult> 之后元素。
这个特定的标签包含一条消息,即“发送成功”。和一个 HTML 编码的 <ReturnIDs>元素,问题不在于 HTML 编码部分,我已经看到了 this question and the accepted answer. 我的问题是我无法同时提取消息和返回 ID。

我尝试使用前面提到的问题中建议的方法,但我失败了,Here是我到目前为止尝试过的。

package main

import (
    "encoding/xml"
    "fmt"
)

var data = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3rg/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <doSendResponse>
            <doSendResult>Send OK.&lt;ReturnIDs&gt;c71cf425f5;e5e4dbb5ca&lt;/ReturnIDs&gt;</doSendResult>
        </doSendResponse>
    </soap:Body>
</soap:Envelope>`

type ResponseBody struct {
    ResponseBody SendResponse `xml:"Body"`
}
type SendResponse struct {
    Result Result `xml:"doSendResponse"`
}
type Result struct {
    RawMessage string `xml:"doSendResult"`
}
type RawMessage struct {
    IDs     string `xml:"ReturnIDs"`
}

func main() {
    var response ResponseBody
    err := xml.Unmarshal([]byte(data), &response)
    if err != nil {
        panic(err.Error())
    }
    fmt.Printf("%+v\n", response)

    var rawMessage RawMessage
    err = xml.Unmarshal([]byte(response.ResponseBody.Result.RawMessage), &rawMessage)
    if err != nil {
        panic(err.Error())
    }
    fmt.Printf("%+v\n", rawMessage)

}

输出:
{ResponseBody:{Result:{RawMessage:Send OK.<ReturnIDs>c71cf425f5;e5e4dbb5ca</ReturnIDs>}}} {IDs:} 我还尝试取消响应,然后尝试解码它,它部分有效,但这种方法存在 3 个主要问题:

  1. 太慢了
  2. 我只能get the ReturnIDsthe message ,而不是两者。
  3. 我相信这只是一个丑陋的 hack,必须有更好的方法来做到这一点(我还不知道。)

那么,我如何提取消息的值(发送成功。)和 <ReturnIDs>

最佳答案

doSendResult标签内容可以通过多种方式解码,我举了一个例子:

play.golang.org/p/NC9YrWqK0k

我定义了两种类型对应于 SOAP 信封主体内的标签:

type (
    SendResponse struct {
        SendResult SendResult `xml:"Body>doSendResponse>doSendResult"`
    }

    SendResult struct {
        RawMessage string   `xml:"-"`
        Text       string   `xml:"-"`
        IDS        []string `xml:"-"`
    }
)

SendResult 类型有一个自定义解码函数来读取原始消息并填充结构

func (sr *SendResult) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    var raw string
    d.DecodeElement(&raw, &start)

    var st struct {
        Contents  string `xml:",chardata"`
        ReturnIDs string `xml:"ReturnIDs"`
    }

    err := xml.Unmarshal([]byte("<xml>"+raw+"</xml>"), &st)
    if err != nil {
        panic(err.Error())
    }

    sr.RawMessage = raw
    sr.Text = st.Contents
    sr.IDS = strings.Split(st.ReturnIDs, ";")

    return nil
}

这是使用方法:

const data = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3rg/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <doSendResponse>
            <doSendResult>Send OK.&lt;ReturnIDs&gt;c71cf425f5;e5e4dbb5ca&lt;/ReturnIDs&gt;</doSendResult>
        </doSendResponse>
    </soap:Body>
</soap:Envelope>`

func main() {
    var sendResponse SendResponse

    err := xml.Unmarshal([]byte(data), &sendResponse)
    if err != nil {
        panic(err.Error())
    }

    fmt.Printf("%+v\n", sendResponse)
}

关于xml - 在 go 中解码特定的 SOAP 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47791873/

有关xml - 在 go 中解码特定的 SOAP 响应的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  3. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  4. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

    在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

  5. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby-on-rails - Ruby on Rails - 需要在每周的特定时间将消息发送到电子邮件 - 2

    我想知道我应该如何着手这个项目。我需要每周向人们发送一次电子邮件。但是,这必须在每周的特定时间自动生成并发送。编码有多难?我需要知道是否有任何书籍可以提供帮助,或者你们中的任何人是否可以指导我。它必须使用ruby​​onrails进行编程。因此有一个网络服务和数据库集成。干杯 最佳答案 为什么这么复杂?您只需安排工作。您可以使用Delayed::Job例如。Delayed::Job让您可以使用run_at符号在特定时间安排作业,如下所示:Delayed::Job.enqueue(SendEmailJob.new(...),:run_

  8. ruby-on-rails - 如果特定语言环境中缺少翻译,如何配置 i18n 以使用 en 语言环境? - 2

    如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback

  9. ruby-on-rails - 如何在 Rails 3 中禁用 XML 解析 - 2

    我想禁用HTTP参数的自动XML解析。但我发现命令仅适用于Rails2.x,它们都不适用于3.0:config.action_controller.param_parsers.deleteMime::XML(application.rb)ActionController::Base.param_parsers.deleteMime::XMLRails3.0中的等价物是什么? 最佳答案 根据CVE-2013-0156的最新安全公告你可以将它用于Rails3.0。3.1和3.2ActionDispatch::ParamsParser::

  10. ruby - 根据要求使用特定的 VCR 磁带 - 2

    情况:使用Rspec、FactoryGirl和VCR测试Rails应用程序。每次创建用户时,都会通过Stripe的API创建关联的Stripe客户。测试时,添加VCR.use_cassette或describe"...",vcr:{cassette_name:'stripe-customer'}do...到涉及用户创建的每个规范。我的实际解决方案如下:RSpec.configuredo|config|config.arounddo|example|VCR.use_cassette('stripe-customer')do|cassette|example.runendendend但这是

随机推荐