如何在导入的XML上使用XPath



我正在尝试解析一个WSDL文件来构建PHP类。虽然有很多工具可以实现这一点,但它们目前都无法记录请求和/或响应的可用SOAPHeader和SOAPFault。

我已经有了足够的理解来构建这个:https://github.com/rquadling/wsdl2php.但后来我遇到了一个与我以前所知不符的服务。

所以。一个示例WSDL文件(被剪切为仅是登录方法和一些导入(。

<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:tns="urn:platform_2012_2.webservices.netsuite.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:platformMsgs="urn:messages_2012_2.platform.webservices.netsuite.com"
xmlns:platformFaults="urn:faults_2012_2.platform.webservices.netsuite.com"
targetNamespace="urn:platform_2012_2.webservices.netsuite.com">
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:import namespace="urn:core_2012_2.platform.webservices.netsuite.com" schemaLocation="https://webservices.eu2.netsuite.com/xsd/platform/v2012_2_0/core.xsd"/>
<xsd:import namespace="urn:faults_2012_2.platform.webservices.netsuite.com" schemaLocation="https://webservices.eu2.netsuite.com/xsd/platform/v2012_2_0/faults.xsd"/>
<xsd:import namespace="urn:messages_2012_2.platform.webservices.netsuite.com" schemaLocation="https://webservices.eu2.netsuite.com/xsd/platform/v2012_2_0/messages.xsd"/>
<xsd:import namespace="urn:common_2012_2.platform.webservices.netsuite.com" schemaLocation="https://webservices.eu2.netsuite.com/xsd/platform/v2012_2_0/common.xsd"/>
<!-- snip -->
</xsd:schema>
</types>
<message name="headers">
<part name="applicationInfo" element="platformMsgs:applicationInfo"/>
<part name="partnerInfo" element="platformMsgs:partnerInfo"/>
<part name="documentInfo" element="platformMsgs:documentInfo"/>
<part name="preferences" element="platformMsgs:preferences"/>
<part name="searchPreferences" element="platformMsgs:searchPreferences"/>
<part name="passport" element="platformMsgs:passport"/>
</message>
<message name="loginRequest">
<part name="parameters" element="platformMsgs:login"/>
</message>
<message name="loginResponse">
<part name="parameters" element="platformMsgs:loginResponse"/>
</message>
<!-- snip -->
<portType name="NetSuitePortType">
<operation name="login">
<input name="loginRequest" message="tns:loginRequest"/>
<output name="loginResponse" message="tns:loginResponse"/>
<fault name="InsufficientPermissionFault" message="tns:InsufficientPermissionFault"/>
<fault name="InvalidAccountFault" message="tns:InvalidAccountFault"/>
<fault name="InvalidCredentialsFault" message="tns:InvalidCredentialsFault"/>
<fault name="InvalidVersionFault" message="tns:InvalidVersionFault"/>
<fault name="ExceededRequestLimitFault" message="tns:ExceededRequestLimitFault"/>
<fault name="UnexpectedErrorFault" message="tns:UnexpectedErrorFault"/>
</operation>
<!-- snip -->
</portType>
<binding name="NetSuiteBinding" type="tns:NetSuitePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="login">
<soap:operation soapAction="login"/>
<input name="loginRequest">
<soap:header message="tns:headers" part="applicationInfo" use="literal"/>
<soap:header message="tns:headers" part="partnerInfo" use="literal"/>
<soap:body use="literal"/>
</input>
<output name="loginResponse">
<soap:body use="literal"/>
</output>
<fault name="InsufficientPermissionFault">
<soap:fault name="InsufficientPermissionFault" use="literal"/>
</fault>
<fault name="InvalidAccountFault">
<soap:fault name="InvalidAccountFault" use="literal"/>
</fault>
<fault name="InvalidCredentialsFault">
<soap:fault name="InvalidCredentialsFault" use="literal"/>
</fault>
<fault name="InvalidVersionFault">
<soap:fault name="InvalidVersionFault" use="literal"/>
</fault>
<fault name="ExceededRequestLimitFault">
<soap:fault name="ExceededRequestLimitFault" use="literal"/>
</fault>
<fault name="UnexpectedErrorFault">
<soap:fault name="UnexpectedErrorFault" use="literal"/>
</fault>
</operation>
<!-- snip -->
</binding>
<service name="NetSuiteService">
<port name="NetSuitePort" binding="tns:NetSuiteBinding">
<soap:address location="https://webservices.eu2.netsuite.com/services/NetSuitePort_2012_2"/>
</port>
</service>
</definitions>

我使用XPath来提取标头(输入和输出(和错误。。。

$xPathMaster['Headers'] = [
'headers_in' => [
'Definitions/Binding/Operation[method]/Input/Header' => '//*[local-name()="definitions"]/*[local-name()="binding"]/*[local-name()="operation"][@name="'.$call.'"]/*[local-name()="input"]/*[local-name()="header"]/@part',
],
'headers_out' => [
'Definitions/Binding/Operation[method]/Output/Header' => '//*[local-name()="definitions"]/*[local-name()="binding"]/*[local-name()="operation"][@name="'.$call.'"]/*[local-name()="output"]/*[local-name()="header"]/@part',
],
'faults' => [
'Definitions/Binding/Operation[method]/fault' => '//*[local-name()="definitions"]/*[local-name()="binding"]/*[local-name()="operation"][@name="'.$call.'"]/*[local-name()="fault"]/@name',
],
];

($call是被调用的方法的名称(。

因此,我的工具知道标头applicationInfologinResponse相关联。

我不确定如何以编程方式找到该类型的结构。

手动地,我知道它作为映射类型存在于消息命名空间导入中https://webservices.eu2.netsuite.com/xsd/platform/v2012_2_0/messages.xsd。。。

<!-- snip -->
<complexType name="ApplicationInfo">
<sequence>
<element name="applicationId" minOccurs="0" type="xsd:string"/>
</sequence>
</complexType>
<element name="applicationInfo" type="platformMsgs:ApplicationInfo"/>

我使用的是PHP的SOAP技术,它可以给我一个类型列表($client->__getTypes(),但这将结构显示为…

struct ApplicationInfo {
string applicationId;
}

(所以它必须在内部运行导入(,但没有提到applicationInfo

因此,尝试通过PHP的DOM,使用XPath查询来实现这一点,我不知道如何"扩展"导入,以便显示实际内容而不是引用。

我有点迷路了。

我根本不是PHP专家,但我认为PHP SOAP技术做得很好。该XSD中的类型列表(XSD类型定义(不应包括applicationInfo,因为applicationInfo是XSD元素声明。(我假设$client是对导入模式的引用,顺便说一句(

作为一般性注释,您可能还需要记住,导入的XSD可能会导入其他XSD,而其他XSD也可能导入其他XSD。。。等等。因此,如果你真的需要处理头/错误的整个结构,那么你需要一直递归嵌套的导入。

最新更新