为什么 soap lib 从列表 entries/arrays 中删除名称空间
Why does soap lib removes namespace from list entries/arrays
我的以下 Javascript 函数使用 Node.js 库“soap”生成并发送 XML SOAP 请求:
async function handle(req, res) {
console.log('details...');
soap.createClientAsync(API.bahn.search, {wsdl_headers: {Authorization: BahnCreds.basic.hash()}}).then(client => {
client.setSecurity(new soap.BasicAuthSecurity(BahnCreds.basic.user, BahnCreds.basic.pwd));
client.addHttpHeader('Authorization', BahnCreds.basic.hash());
// console.debug(client.describe()); // Methodenliste
const args = {
RequestData: {
attributes: {
ot: fns.format(new Date(), 'yyyyMMddhhmmss'),
},
'WL5G3N3:TariffIdentificationH': {
attributes: {
t: req.body.ticketid,
c: req.body.class,
}
},
'WL5G3N3:TravelerList': {
Traveler: {
attributes: {
age: 35
}
}
},
'WL5G3N3:ScheduleH': {
attributes: {
sid: req.body.sid,
dt: req.body.date,
},
'WL5G3N3:TrainList': {
'WL5G3N3:Train': req.body.trains.map(train => {
return {attributes: train};
})
}
},
},
Header: header.get(),
};
console.log(JSON.stringify(args));
const callback = (error, result) => {
console.debug(client.lastRequest);
if(!error) {
return res.json({
result: result,
type: 'success',
})
}
return res.json(Object.assign({},
Errors.ERR__FEHLER_BEI_ABFRAGE,
{details: error}));
};
return client
.WSDReiseAuskunftInterface
.WSDReiseAuskunftPort
.Angebotsdetails(args, callback);
});
}
生成的 XML 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:WL5G3N1="http://www.bahn.de/webservices/dritte/angebotssuche/request"
xmlns:WL5G3N2="http://www.bahn.de/webservices/dritte/angebotssuche/response"
xmlns:WL5G3N3="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns:WL5G3N4="http://www.bahn.de/webservices/dritte/angebotsdetails/response"
xmlns:WL5G3N5="http://www.bahn.de/webservices/dritte/ping/request"
xmlns:WL5G3N6="http://www.bahn.de/webservices/dritte/ping/response"
xmlns:WL5G3N7="http://www.bahn.de/webservices/dritte/monitoring/request"
xmlns:WL5G3N8="http://www.bahn.de/webservices/dritte/monitoring/response"
xmlns:WL5G3N9="http://www.bahn.de/webservices/dritte"
xmlns:adreq="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns:adres="http://www.bahn.de/webservices/dritte/angebotsdetails/response"
xmlns:asreq="http://www.bahn.de/webservices/dritte/angebotssuche/request"
xmlns:asres="http://www.bahn.de/webservices/dritte/angebotssuche/response"
xmlns:monreq="http://www.bahn.de/webservices/dritte/monitoring/request"
xmlns:monres="http://www.bahn.de/webservices/dritte/monitoring/response"
xmlns:pingreq="http://www.bahn.de/webservices/dritte/ping/request"
xmlns:pingres="http://www.bahn.de/webservices/dritte/ping/response">
<soap:Header></soap:Header>
<soap:Body>
<WL5G3N3:AngebotsdetailsRequest xmlns:WL5G3N3="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns="http://www.bahn.de/webservices/dritte/angebotsdetails/request">
<WL5G3N3:RequestData ot="20201202052152">
<WL5G3N3:TariffIdentificationH t="TCK#13#0#0#0#S2#6290#" c="2"></WL5G3N3:TariffIdentificationH>
<WL5G3N3:TravelerList>
<db:Traveler age="35"
xmlns:db="http://www.bahn.de/webservices/dritte/datatypes/db"></db:Traveler>
</WL5G3N3:TravelerList>
<WL5G3N3:ScheduleH sid="0" dt="20201204">
<WL5G3N3:TrainList>
<ns1:Train arr="00d00:36:00" d="8000207" dep="00d00:14:00" dn="Köln Hbf" lt="Transport" s="8000085" sn="Düsseldorf Hbf" tid="0.0" tn="ICE 842"></ns1:Train>
<ns1:Train arr="00d01:25:00" d="8000044" dep="00d00:56:00" dn="Bonn Hbf" lt="Transport" s="8000207" sn="Köln Hbf" tid="0.1" tn="RB 25401"></ns1:Train>
</WL5G3N3:TrainList>
</WL5G3N3:ScheduleH>
</WL5G3N3:RequestData>
<WL5G3N3:Header l="DE" t="" us="" pwd="" sig="" tnr=""></WL5G3N3:Header>
</WL5G3N3:AngebotsdetailsRequest>
</soap:Body>
</soap:Envelope>
此请求导致错误,因为 WL5G3N3:Train
已更改为 ns1:Train
。我认为,这与 WL5G3N3:Train
是一个数组有关。
我现在的问题是:为什么会这样?有谁知道,我必须如何配置 SOAP 以使数组不会丢失其名称空间?
解决方案是在创建客户端后显式覆盖命名空间。
client.wsdl.definitions.xmlns.ns1 = http://your-namespace-url...;
client.wsdl.xmlnsInEnvelope = client.wsdl._xmlnsMap()
然后我们也可以摆脱硬编码的命名空间。该函数现在看起来像这样:
async function handle(req, res) {
console.log('details...');
soap.createClientAsync(API.bahn.search, {wsdl_headers: {Authorization: BahnCreds.basic.hash()}}).then(client => {
client.setSecurity(new soap.BasicAuthSecurity(BahnCreds.basic.user, BahnCreds.basic.pwd));
client.addHttpHeader('Authorization', BahnCreds.basic.hash());
// THIS WAS/IS IMPORTANT
client.wsdl.definitions.xmlns.ns1 = API.bahn.ns.details;
client.wsdl.xmlnsInEnvelope = client.wsdl._xmlnsMap()
const args = {
RequestData: {
attributes: {
ot: fns.format(new Date(), 'yyyyMMddhhmmss'),
},
TariffIdentificationH: {
attributes: {
t: req.body.ticketid,
c: req.body.class,
}
},
TravelerList: {
Traveler: {
attributes: {
age: 35
}
}
},
ScheduleH: {
attributes: {
sid: req.body.sid,
dt: req.body.date,
},
TrainList: {
Train: req.body.trains
}
},
},
Header: header.get(),
};
const callback = (error, result) => {
if(!error) {
return res.json({
result: result,
type: 'success',
})
}
return res.json(Object.assign({},
Errors.ERR__FEHLER_BEI_ABFRAGE,
{details: error}));
};
return client
.WSDReiseAuskunftInterface
.WSDReiseAuskunftPort
.Angebotsdetails(args, callback);
});
}
我的以下 Javascript 函数使用 Node.js 库“soap”生成并发送 XML SOAP 请求:
async function handle(req, res) {
console.log('details...');
soap.createClientAsync(API.bahn.search, {wsdl_headers: {Authorization: BahnCreds.basic.hash()}}).then(client => {
client.setSecurity(new soap.BasicAuthSecurity(BahnCreds.basic.user, BahnCreds.basic.pwd));
client.addHttpHeader('Authorization', BahnCreds.basic.hash());
// console.debug(client.describe()); // Methodenliste
const args = {
RequestData: {
attributes: {
ot: fns.format(new Date(), 'yyyyMMddhhmmss'),
},
'WL5G3N3:TariffIdentificationH': {
attributes: {
t: req.body.ticketid,
c: req.body.class,
}
},
'WL5G3N3:TravelerList': {
Traveler: {
attributes: {
age: 35
}
}
},
'WL5G3N3:ScheduleH': {
attributes: {
sid: req.body.sid,
dt: req.body.date,
},
'WL5G3N3:TrainList': {
'WL5G3N3:Train': req.body.trains.map(train => {
return {attributes: train};
})
}
},
},
Header: header.get(),
};
console.log(JSON.stringify(args));
const callback = (error, result) => {
console.debug(client.lastRequest);
if(!error) {
return res.json({
result: result,
type: 'success',
})
}
return res.json(Object.assign({},
Errors.ERR__FEHLER_BEI_ABFRAGE,
{details: error}));
};
return client
.WSDReiseAuskunftInterface
.WSDReiseAuskunftPort
.Angebotsdetails(args, callback);
});
}
生成的 XML 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:WL5G3N1="http://www.bahn.de/webservices/dritte/angebotssuche/request"
xmlns:WL5G3N2="http://www.bahn.de/webservices/dritte/angebotssuche/response"
xmlns:WL5G3N3="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns:WL5G3N4="http://www.bahn.de/webservices/dritte/angebotsdetails/response"
xmlns:WL5G3N5="http://www.bahn.de/webservices/dritte/ping/request"
xmlns:WL5G3N6="http://www.bahn.de/webservices/dritte/ping/response"
xmlns:WL5G3N7="http://www.bahn.de/webservices/dritte/monitoring/request"
xmlns:WL5G3N8="http://www.bahn.de/webservices/dritte/monitoring/response"
xmlns:WL5G3N9="http://www.bahn.de/webservices/dritte"
xmlns:adreq="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns:adres="http://www.bahn.de/webservices/dritte/angebotsdetails/response"
xmlns:asreq="http://www.bahn.de/webservices/dritte/angebotssuche/request"
xmlns:asres="http://www.bahn.de/webservices/dritte/angebotssuche/response"
xmlns:monreq="http://www.bahn.de/webservices/dritte/monitoring/request"
xmlns:monres="http://www.bahn.de/webservices/dritte/monitoring/response"
xmlns:pingreq="http://www.bahn.de/webservices/dritte/ping/request"
xmlns:pingres="http://www.bahn.de/webservices/dritte/ping/response">
<soap:Header></soap:Header>
<soap:Body>
<WL5G3N3:AngebotsdetailsRequest xmlns:WL5G3N3="http://www.bahn.de/webservices/dritte/angebotsdetails/request"
xmlns="http://www.bahn.de/webservices/dritte/angebotsdetails/request">
<WL5G3N3:RequestData ot="20201202052152">
<WL5G3N3:TariffIdentificationH t="TCK#13#0#0#0#S2#6290#" c="2"></WL5G3N3:TariffIdentificationH>
<WL5G3N3:TravelerList>
<db:Traveler age="35"
xmlns:db="http://www.bahn.de/webservices/dritte/datatypes/db"></db:Traveler>
</WL5G3N3:TravelerList>
<WL5G3N3:ScheduleH sid="0" dt="20201204">
<WL5G3N3:TrainList>
<ns1:Train arr="00d00:36:00" d="8000207" dep="00d00:14:00" dn="Köln Hbf" lt="Transport" s="8000085" sn="Düsseldorf Hbf" tid="0.0" tn="ICE 842"></ns1:Train>
<ns1:Train arr="00d01:25:00" d="8000044" dep="00d00:56:00" dn="Bonn Hbf" lt="Transport" s="8000207" sn="Köln Hbf" tid="0.1" tn="RB 25401"></ns1:Train>
</WL5G3N3:TrainList>
</WL5G3N3:ScheduleH>
</WL5G3N3:RequestData>
<WL5G3N3:Header l="DE" t="" us="" pwd="" sig="" tnr=""></WL5G3N3:Header>
</WL5G3N3:AngebotsdetailsRequest>
</soap:Body>
</soap:Envelope>
此请求导致错误,因为 WL5G3N3:Train
已更改为 ns1:Train
。我认为,这与 WL5G3N3:Train
是一个数组有关。
我现在的问题是:为什么会这样?有谁知道,我必须如何配置 SOAP 以使数组不会丢失其名称空间?
解决方案是在创建客户端后显式覆盖命名空间。
client.wsdl.definitions.xmlns.ns1 = http://your-namespace-url...;
client.wsdl.xmlnsInEnvelope = client.wsdl._xmlnsMap()
然后我们也可以摆脱硬编码的命名空间。该函数现在看起来像这样:
async function handle(req, res) {
console.log('details...');
soap.createClientAsync(API.bahn.search, {wsdl_headers: {Authorization: BahnCreds.basic.hash()}}).then(client => {
client.setSecurity(new soap.BasicAuthSecurity(BahnCreds.basic.user, BahnCreds.basic.pwd));
client.addHttpHeader('Authorization', BahnCreds.basic.hash());
// THIS WAS/IS IMPORTANT
client.wsdl.definitions.xmlns.ns1 = API.bahn.ns.details;
client.wsdl.xmlnsInEnvelope = client.wsdl._xmlnsMap()
const args = {
RequestData: {
attributes: {
ot: fns.format(new Date(), 'yyyyMMddhhmmss'),
},
TariffIdentificationH: {
attributes: {
t: req.body.ticketid,
c: req.body.class,
}
},
TravelerList: {
Traveler: {
attributes: {
age: 35
}
}
},
ScheduleH: {
attributes: {
sid: req.body.sid,
dt: req.body.date,
},
TrainList: {
Train: req.body.trains
}
},
},
Header: header.get(),
};
const callback = (error, result) => {
if(!error) {
return res.json({
result: result,
type: 'success',
})
}
return res.json(Object.assign({},
Errors.ERR__FEHLER_BEI_ABFRAGE,
{details: error}));
};
return client
.WSDReiseAuskunftInterface
.WSDReiseAuskunftPort
.Angebotsdetails(args, callback);
});
}