#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. Большое спасибо за отличное объяснение! Это огромная помощь, ура, приятель!