在PHP中读取SOAP XML
我对我的客户端执行SOAP调用。它将一个XML文档作为字符串返回(这是一种解决方法,我无能为力)。我有一个变量的XML,我需要阅读这个XML来获取我想要的信息。在PHP中读取SOAP XML
我在查找字段DomesticCustomer
,Addresses
和GridOwner
。我想如果有人帮我找到DomesticCustomer
-我可以自己做其余的事情。
注意:在本例中,每个字段下只有一个条目,但可能有多个条目,所以我需要能够对此进行foreach。
注意事项#2:由于我使用的客户端有一些奇怪的解决方法,因此它的响应(xml)是一个简单的字符串。
的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:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<MeteringPointIdResponse xmlns="http://www.ediel.no/schemas/public/nubix/MeteringPointIdResponse">
<RequestId xmlns="">3423424234</RequestId>
<Requestor xmlns="">
<GLN>234234234</GLN>
</Requestor>
<Customers xmlns="">
<DomesticCustomer>
<LastName>Name</LastName>
<FirstName>Name</FirstName>
<BirthDate>xxx-xx-xx</BirthDate>
<MeterNumber>xxxxx</MeterNumber>
<Addresses>
<Address>
<Address1>345345</Address1>
<PostCode>3514</PostCode>
<Location>xxxxxx</Location>
<CountryCode>xx</CountryCode>
<Installation>
<Description>xxxxx</Description>
<MeteringPointId>xxxxxxxxxxxxxxx</MeteringPointId>
<MeteringMethod>xxxxxx</MeteringMethod>
<InstallationStatus>xxxx</InstallationStatus>
<LastReadOffDate>xxxx-xx-xx</LastReadOffDate>
</Installation>
<GridOwner>
<GLN>xxxxxxx</GLN>
<Name>xxxxxxxx</Name>
<ProdatAddress>
<InterchangeRecipient>
<Id>xxxxxxx</Id>
<Qualifier>xx</Qualifier>
<Subaddress>xxxxx</Subaddress>
</InterchangeRecipient>
<Party>
<Id>xxxxxxxxxx</Id>
<CodeListResponsible>xxxx</CodeListResponsible>
</Party>
<EDISyntax>
<CharSet>xxx</CharSet>
<SyntaxId>xxxx</SyntaxId>
</EDISyntax>
<SMTPAddress>[email protected]</SMTPAddress>
</ProdatAddress>
</GridOwner>
</Address>
</Addresses>
</DomesticCustomer>
</Customers>
</MeteringPointIdResponse>
</soap:Body>
</soap:Envelope>
如果您使用内置的库PHP,它解析响应并返回一个混合的对象/数组对象,它是与比XML无穷容易处理
编辑:由于您使用的是PHP内置的客户端,因此这里是我编写的一个简单的类。它 “变平” 的反响,可以很容易地检索像responces:
$soap = new SOAP($wsdl, $options);
$soap->call("stuff goes here");
$soap->find("what you are looking for goes here");
/**
* @author Troy Knapp
* @copyright 2011
*
* @version .1.1
*/
class Soap {
//***VARIABLES***//
var $request; //..............string; holds last soap request
var $requestHeaders; //.......string; holds the headers for the last request
var $response; //.............string; xml response
var $responseHeaders; //......string; holds the headers for the last response
var $result; //...............array; the soap response parsed into an array
var $wsdlLocation; //.........string; url for the wsdl
var $parameters; //...........array; saved array of parameters
var $function; //.............string; name of function to be accessed
var $findResult = array();
var $flatArray = array(); //..array; holds an easy to search array
//
//***OBJECTS***//
var $client; //...................instance of SoapClient
var $exception; //................obj; SoapFault exception object
//
//***DEFAULTS***//
public $options = array(
'trace' => 1
);
function __construct($wsdl, $options = false) {
if ($options == false) {
$options = $this->options;
} else {
$this->options = $options;
}
$this->wsdlLocation = $wsdl;
$this->client = new SoapClient($wsdl, $options);
}
/*
* Executes a given function when supplied the proper function name,
* parameters and options.
*/
function call($function, $parameters, $options=NULL) {
$this->function = $function;
$this->parameters = $parameters;
try {
//$this->response = $this->client->__soapCall($function, $parameters, $options);
$this->response = $this->client->$function($parameters, $options);
} catch (SoapFault $exception) {
$this->$exception = $exception;
}
//get info about the last request
$this->request = $this->client->__getLastRequest();
$this->requestHeaders = $this->client->__getLastRequestHeaders();
//more info about the last responce
$this->responseHeaders = $this->client->__getLastResponseHeaders();
//set up an easily searchable array of results
$this->flatten();
return $this->response;
}
/*
* Prints all kinds of interesting info about what went on for debugging
* purposes
*/
function printInfo() {
echo '<h2>SoapClient Info:</h2>';
echo 'wsdl location: ' . $this->wsdl_location . '<br/>';
echo 'SoapClient Options:';
echoPre($this->options);
echo '<h2>Call Info:</h2>';
echo 'Function Name: ' . $this->function . '<br/>';
echo 'Parameters: ';
echoPre($this->parameters);
echo '<h2>Last Request: <br></h2>';
echo $this->format($this->request);
echo '<h2>Request Headers: <br></h2>';
echo $this->format($this->requestHeaders);
echo '<h2>Last Response: <br></h2>';
echoPre($this->response);
echo '<h2>Response Headers: <br></h2>';
echo $this->format($this->responseHeaders);
}
/*
* Formats the xml to make it nice and purdy for display and debugging
* purposes
*/
function format($xml) {
// add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
$xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
// now indent the tags
$token = strtok($xml, "\n");
$result = ''; // holds formatted version as it is built
$pad = 0; // initial indent
$matches = array(); // returns from preg_matches()
// scan each line and adjust indent based on opening/closing tags
while ($token !== false) :
// test for the various tag states
// 1. open and closing tags on same line - no change
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
$indent = 0;
// 2. closing tag - outdent now
elseif (preg_match('/^<\/\w/', $token, $matches)) :
$pad--;
// 3. opening tag - don't pad this one, only subsequent tags
elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
$indent = 1;
// 4. no indentation needed
else :
$indent = 0;
endif;
// pad the line with the required number of leading spaces
$line = str_pad($token, strlen($token) + $pad, ' ', STR_PAD_LEFT);
$result .= $line . "\n"; // add to the cumulative result, with linefeed
$token = strtok("\n"); // get the next token
$pad += $indent; // update the pad size for subsequent lines
endwhile;
$result = highlight_string($result);
//nl2br(htmlentities($result));
return $result;
}
/*
* Searches the pre flattened array for a given key. If there is only one
* result, this will return a single value, if there are multiple results,
* it will return an array of values.
*
* @param string; $search - search for a response with this key
*/
function find($search=false) {
if ($search == false) {
return $this->flatArray;
} else {
if (isset($this->flatArray[$search])) {
$result = $this->flatArray[$search];
} else {
return false;
}
}
if(count($result)==1){
return $result[0];
}
else{
return $result;
}
}
/*
* This method flattens an array/object result into an array that is easy
* to search through. Search terms are set as keys with results set as
* arrays owned by said keys.
*/
function flatten($array=false) {
if ($array == false) {
$array = $this->response;
}
if (is_object($array)) {
//get the variables of object
$array = get_object_vars($array);
}
//howdy('array');
//echoPre($array);
//echo "_______________<br>";
if (is_array($array)) {
//loop through the sub elements and make sure they are arrays
foreach ($array as $key => $value) {
//if it's an object, we need to convert it to an array
if (is_object($value)) {
//get the variables of object
$value = get_object_vars($value);
}
//echo "key: $key value: ";
//echoPre($value);
//echo "_______________<br>";
//push the key=>value pairs to the flat array
if (!isset($this->flatArray[$key])) {
$this->flatArray[$key] = array();
}
array_push($this->flatArray[$key], $value);
if (is_array($value)) {
$this->flatten($value);
}
}
}
}
function getWSDL() {
$wsdl = file_get_contents($this->wsdlLocation);
}
}
因为这是我们的提供者的一种解决方法,所以在返回时XML只是一个简单的字符串。我需要获取这个循环的xpath才能工作。 – OptimusCrime 2012-02-20 15:38:52
我已经走下了试图将XML转换为数组的兔子洞,然后遍历该数组尝试解析它的值......除非你比我更聪明,我不会推荐它。 – 2012-02-20 15:49:48
看到我自己的回答belove。这并不困难。 – OptimusCrime 2012-02-20 15:54:51
使用http://php.net/manual/en/class.soapclient.php(在PHP5证明你)
我是......那根本不是这个问题的答案。 – OptimusCrime 2012-02-20 15:39:05
对不起,我读得太快,并认为是错误的东西,我的坏:) – BenOfTheNorth 2012-02-20 15:48:46
它是那么简单。忘记注册名称空间。的
$xml = simplexml_load_string($xml);
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
foreach ($xml->xpath('//DomesticCustomer') as $item)
{
print_r($item);
}
你没有在XPath查询中使用名称空间,所以这与注册名称空间无关。证明:http://codepad.viper-7.com/KuvI4C – Gordon 2012-02-20 16:03:13
可能重复[从其他文件的类函数变量](http://stackoverflow.com/questions/9363308/get-variable-from-other-files-class-function) – Gordon 2012-02-20 15:40:14
你甚至阅读我的问题?这是关于阅读一个变量中的XML文档。尽可能远离相关事物。 – OptimusCrime 2012-02-20 15:43:42
那又如何不重复呢?用SimpleXML加载变量,然后可以像显示的那样访问它。除了如何解析和处理XML之外,SOAP或HTML经常被回答,还有另一个问题要求如何从XML文档中获取' '。在你的问题中没有任何具体的东西来证明你没有关闭它。请看右边的相关部分。 –
Gordon
2012-02-20 15:54:49