You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP SoapClient生成含重复instrument节点的XML问题求助

解决PHP SoapClient生成重复instrument节点的问题

我明白你现在遇到的困扰:要生成包含多个重复<ns1:instrument>节点的SOAP请求XML,但PHP关联数组没法存储相同键,尝试用SoapVar后<ns1:instruments>节点还变成空的了——这个坑我之前也踩过,咱们一步步来解决。

先回顾下你需要生成的目标XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001"> 
  <SOAP-ENV:Body> 
    <ns1:submitGetHistoryRequest> 
      <ns1:headers> 
        <ns1:daterange> 
          <ns1:period> 
            <ns1:start>2018-05-08</ns1:start> 
            <ns1:end>2018-05-08</ns1:end> 
          </ns1:period> 
        </ns1:daterange> 
      </ns1:headers> 
      <ns1:fields> 
        <ns1:field>PX_LAST</ns1:field> 
      </ns1:fields> 
      <ns1:instruments> 
        <ns1:instrument> 
          <ns1:id>US0000000002</ns1:id> 
          <ns1:yellowkey>Equity</ns1:yellowkey> 
          <ns1:type>ISIN</ns1:type> 
        </ns1:instrument> 
        <ns1:instrument> 
          <ns1:id>US0000000001</ns1:id> 
          <ns1:yellowkey>Equity</ns1:yellowkey> 
          <ns1:type>ISIN</ns1:type> 
        </ns1:instrument> 
      </ns1:instruments> 
    </ns1:submitGetHistoryRequest> 
  </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>

你之前的代码问题出在两个核心点:

  1. 直接给$options->instruments赋值数组,SOAP期望<ns1:instruments>节点下包含多个<ns1:instrument>子节点,正确结构应该是instruments对象拥有一个instrument属性,这个属性是数组。
  2. SoapVar的命名空间用错了,你用了http://soapinterop.org/xsd,但必须匹配目标服务的命名空间http://services.bloomberg.com/datalicense/dlws/ps/20071001,且类型名称应该是instrument而非stdClass。

方法一:修正SoapVar的使用方式

调整你原来的代码,修正结构和命名空间:

$options = new \stdClass();
$options->headers = new \stdClass();
$options->headers->daterange = new \stdClass();
$options->headers->daterange->period = new \stdClass();
$options->headers->daterange->period->start = '2018-05-08';
$options->headers->daterange->period->end = '2018-05-08';
$options->fields = new \stdClass();
$options->fields->field = 'PX_LAST';

// 先创建instruments对象,内部的instrument属性是数组
$options->instruments = new \stdClass();
$options->instruments->instrument = [];

// 第一个instrument
$instrument1 = new \stdClass();
$instrument1->id = 'US0000000002';
$instrument1->type = 'ISIN';
$instrument1->yellowkey = 'Equity';
$options->instruments->instrument[] = new \SoapVar(
    $instrument1,
    SOAP_ENC_OBJECT,
    'instrument',
    'http://services.bloomberg.com/datalicense/dlws/ps/20071001', // 正确的目标命名空间
    'instrument'
);

// 第二个instrument
$instrument2 = new \stdClass();
$instrument2->id = 'US0000000001';
$instrument2->type = 'ISIN';
$instrument2->yellowkey = 'Equity';
$options->instruments->instrument[] = new \SoapVar(
    $instrument2,
    SOAP_ENC_OBJECT,
    'instrument',
    'http://services.bloomberg.com/datalicense/dlws/ps/20071001',
    'instrument'
);

// 初始化SoapClient并调用方法
$client = new \SoapClient(null, [
    'location' => '你的实际服务地址',
    'uri' => 'http://services.bloomberg.com/datalicense/dlws/ps/20071001',
    'trace' => true, // 开启trace以便查看生成的请求XML
]);

$result = $client->submitGetHistoryRequest($options);

// 查看生成的请求XML
echo $client->__getLastRequest();

方法二:直接用数组结构(更简洁)

其实不需要用SoapVar,只要数组结构正确,SoapClient会自动把数组转换成重复的节点:

$requestParams = [
    'headers' => [
        'daterange' => [
            'period' => [
                'start' => '2018-05-08',
                'end' => '2018-05-08'
            ]
        ]
    ],
    'fields' => [
        'field' => 'PX_LAST'
    ],
    'instruments' => [
        'instrument' => [
            [
                'id' => 'US0000000002',
                'type' => 'ISIN',
                'yellowkey' => 'Equity'
            ],
            [
                'id' => 'US0000000001',
                'type' => 'ISIN',
                'yellowkey' => 'Equity'
            ]
        ]
    ]
];

$client = new \SoapClient(null, [
    'location' => '你的实际服务地址',
    'uri' => 'http://services.bloomberg.com/datalicense/dlws/ps/20071001',
    'trace' => true,
    'use' => SOAP_LITERAL, // 确保使用字面量模式,避免序列化异常
]);

// 用SoapParam包装参数,指定参数名称
$result = $client->submitGetHistoryRequest(new \SoapParam($requestParams, 'submitGetHistoryRequest'));

// 查看生成的XML
echo $client->__getLastRequest();

这两种方法都能生成你需要的包含多个<ns1:instrument>节点的XML,第二种方法更简洁,推荐优先使用。

内容的提问来源于stack exchange,提问作者ზურა კუპატაძე

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:06:51