Анализировать XML-данные из ответа PHP SOAP

#php #xml #soap

#php #xml #soap

Вопрос:

Я успешно смог получить ответ от API, с которым я работаю, с помощью Брайана Дрисколла, но у меня возникли проблемы с анализом этих XML-данных. Вот скрипт для получения ответа и возвращенных XML-данных —

 $clientC = new SoapClient('http://webservice.nada.com/vehicles/vehicle.asmx?wsdl',array('trace' => 1,'exceptions' => 1, 'cache_wsdl' => 0));

$params = new stdClass();
$params->Token = $token;
$params->Period = 1;
$params->VehicleType = "UsedCar";
$params->Vin = '5YFBURHE3FP331896';
$params->Region = 10;
$params->Mileage = 100;

$result = $clientC->getDefaultVehicleAndValueByVin(array('vehicleRequest' => $params));

$xml = htmlspecialchars($clientC->__getLastResponse());
  

Это возвращает —

 <?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>
            <getDefaultVehicleAndValueByVinResponse xmlns="http://webservice.nada.com/">
                <getDefaultVehicleAndValueByVinResult>
                    <Uid>1182699</Uid>
                    <VehicleYear>2015</VehicleYear>
                    <MakeCode>47</MakeCode>
               </getDefaultVehicleAndValueByVinResult> 
           </getDefaultVehicleAndValueByVinResponse>
      </soap:Body>
    </soap:Envelope>
  

Я хотел бы либо проанализировать XML и получить что-то вроде

 $vehicle_year = $xml->VehicleYear;
  

Я пытался —

 $xml = htmlspecialchars($clientC->__getLastResponse());

$response = strtr($xml, ['</soap:' => '</', '<soap:' => '<']);
$output = json_decode(json_encode(simplexml_load_string($response)));
var_dump($output->Body->getHighVehicleAndValueByVinResponse->VehicleYear);
  

Но возвращает NULL

Комментарии:

1. Почему вы пытаетесь обрабатывать xml как json? PHP имеет несколько расширений xml. Взгляните на них

2. Спасибо, я просто лучше знаком с JSON, не часто использовал XML

3. Кстати, не уничтожает ли htmlspecialchars ваш xml, поскольку он заменяет < и > ?

4. @kuh-chan да, вы правы, удаление этого было обязательным!

Ответ №1:

Это обычная проблема наличия различных пространств имен, по которым вам нужно перемещаться. Корневой узел определяет, xmlns:soap поэтому вы можете использовать это без необходимости что-либо делать, поэтому XPath использует //soap:Body/* для поиска элемента внутри тега body, поскольку xpath() возвращает список совпадающих узлов, используйте [0] , чтобы просто выбрать единственный.

Поскольку все основные данные находятся в пространстве имен по умолчанию (определяемом как xmlns="http://webservice.nada.com/" ), вы можете извлечь их все с помощью $data->children("http://webservice.nada.com/") . Теперь это позволяет вам использовать стандартную объектную нотацию для доступа к значениям.

Следует отметить одну вещь: хотя echo они автоматически преобразуются в строку, если вы используете эти значения в другом месте, вам может потребоваться преобразовать их с помощью (string) , поскольку элемент фактически является SimpleXMLElement.

 $data = <<< 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>
        <getDefaultVehicleAndValueByVinResponse xmlns="http://webservice.nada.com/">
            <getDefaultVehicleAndValueByVinResult>
            <Uid>1182699</Uid>
            <VehicleYear>2015</VehicleYear>
            <MakeCode>47</MakeCode>
            </getDefaultVehicleAndValueByVinResult> 
       </getDefaultVehicleAndValueByVinResponse>
    </soap:Body>
</soap:Envelope>
XML;

$xml = simplexml_load_string($data);
$data = $xml->xpath("//soap:Body/*")[0];
$details = $data->children("http://webservice.nada.com/");
echo (string)$details->getDefaultVehicleAndValueByVinResult->VehicleYear;
  

Комментарии:

1. Большое спасибо за отличное объяснение! Это огромная помощь, ура, приятель!