2012-02-20 4 views
0

클라이언트에 SOAP 호출을 수행합니다. XML 문서를 문자열로 반환합니다 (이 방법은 해결할 수없는 해결책입니다). 나는 변수에 XML을 가지고 있으며 원하는 정보를 얻기 위해이 XML을 읽어야한다.PHP에서 SOAP XML 읽기

DomesticCustomer, AddressesGridOwner 필드를 찾고 있습니다. 나는 누군가가 내가 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> 
+0

가능한 중복 [다른 파일의 클래스 함수의 변수를 가져옵니다 (http://stackoverflow.com/questions/9363308/get-variable-from-other-files-class-function) – Gordon

+0

당신은 읽지 않았다 내 질문? 이것은 변수에있는 XML 문서를 읽는 것에 관한 것입니다. 가능한 한 관련성이 떨어진다. – OptimusCrime

+0

그리고 그게 어떻게 중복되지 않습니까? 변수를 SimpleXML로로드하면 그림과 같이 액세스 할 수 있습니다. XML을 파싱하고 처리하는 방법 외에도 SOAP 또는 HTML이 너무 자주 응답되어 XML 문서에서' '를 얻는 방법을 묻는 또 다른 질문이 있습니다. 질문을 닫지 않는 것을 정당화 할 수있는 구체적인 것은 없습니다. 오른쪽의 관련 섹션을보십시오. – Gordon

답변

1

당신이 PHP를 위해 라이브러리에 내장 사용하는 경우, 그것은 응답을 구문 분석하고 XML보다 처리하는 무한 쉽게 혼합 객체/배열 객체를 반환

편집 : php의 내장 클라이언트를 사용하고 있기 때문에 여기에 간단한 클래스를 작성했습니다. 그것은 responce "을 평평하게"하고 쉽게 같은 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); 
} 

}

+0

이것은 공급자를위한 해결 방법이므로 반환 된 XML은 단순한 문자열입니다. 이 루프가 작동하려면 xpath를 얻어야합니다. – OptimusCrime

+0

XML을 배열로 변환하려고 시도한 토끼의 구멍을 내려 놓은 다음 해당 배열을 반복하여 배열의 값을 파싱합니다. 내가 현재보다 훨씬 똑똑하지 않으면 내가 추천하지 않습니다. –

+0

내 대답을 참조하십시오. 그렇게 어렵지 않았습니다. – OptimusCrime

0

(PHP5에 증명을). 네임 스페이스 등록을 잊어 버렸습니다. 의

$xml = simplexml_load_string($xml); 
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/'); 
foreach ($xml->xpath('//DomesticCustomer') as $item) 
{ 
    print_r($item); 
} 
+0

XPath 쿼리에서 네임 스페이스를 사용하고 있지 않으므로 네임 스페이스 등록과 관련이 없습니다. 증명 : http://codepad.viper-7.com/KuvI4C – Gordon