在PHP中读取SOAP XML


Reading SOAP XML in PHP

我对我的客户端进行SOAP调用。它以字符串的形式返回一个XML文档(这是一个我无能为力的解决方法)。我在一个变量中有XML,我需要读取这个XML来获取我想要的信息。

我正在查找字段DomesticCustomerAddressesGridOwner。我想如果有人帮我进入DomesticCustomer部分,我可以自己完成剩下的部分。

注意:在这个例子中,每个字段下只有一个条目,但可能有多个条目,所以我需要能够预先处理这个条目。

注意#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>test@hey.com</SMTPAddress>
                                </ProdatAddress>
                            </GridOwner>
                        </Address>
                    </Addresses>
                </DomesticCustomer>
            </Customers>
        </MeteringPointIdResponse>
    </soap:Body>
</soap:Envelope>

如果使用php的内置库,它会解析响应并返回一个比xml 更容易处理的混合对象/数组对象

编辑:由于您使用的是php的内置客户端,这里有一个我围绕它编写的简单类。它"平坦"了响应,并使检索响应变得容易,如:

$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 = simplexml_load_string($xml);
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
foreach ($xml->xpath('//DomesticCustomer') as $item)
{
    print_r($item);
}

使用http://php.net/manual/en/class.soapclient.php(在PHP5上验证您的)