Проблема с Simlpexml и registerxpathnamespace в теле ответа мыла

Вот этот XML: (a.xml)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:ser="http://www.example.com/v1/services">
<soapenv:Header/>
<soapenv:Body>
<ser:getAnalyticalDeliveryEstimatesRequest>
<ser:buyer>
<ser:buyerId>1233</ser:buyerId>
<ser:toCountry>IN</ser:toCountry>
<ser:toZip>110001</ser:toZip>
</ser:buyer>
<ser:item>
<ser:id>25164</ser:id>
<ser:categoryId>15032</ser:categoryId>
<ser:seller>
<ser:sellerId>11997</ser:sellerId>
<ser:fromCountry>IN</ser:fromCountry>
</ser:seller>
<ser:transactionId>0</ser:transactionId>
</ser:item>
</ser:getAnalyticalDeliveryEstimatesRequest>
</soapenv:Body>
</soapenv:Envelope>

Код PHP для анализа этого:

$xml = simplexml_load_file( 'a.xml', NULL, NULL, 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('ser', 'http://www.example.com/v1/services');

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );

print_r($xpath);

Это не дает никаких данных.

Пожалуйста, дайте мне знать, если я делаю это неправильно.

1

Решение

Довольно странно видеть, что это не работает, но вы также можете использовать это:

$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXpath($dom);
$element = $xpath->query('//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest');

foreach($element->item(0)->childNodes as $node) {
// perform your actions here
}

Пример вывода

Редактировать: Также это еще один способ:

$xml_string ='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:ser="http://www.example.com/v1/services">
<soapenv:Header/>
<soapenv:Body>
<ser:getAnalyticalDeliveryEstimatesRequest>
<ser:buyer>
<ser:buyerId>1233</ser:buyerId>
<ser:toCountry>IN</ser:toCountry>
<ser:toZip>110001</ser:toZip>
</ser:buyer>
<ser:item>
<ser:id>25164</ser:id>
<ser:categoryId>15032</ser:categoryId>
<ser:seller>
<ser:sellerId>11997</ser:sellerId>
<ser:fromCountry>IN</ser:fromCountry>
</ser:seller>
<ser:transactionId>0</ser:transactionId>
</ser:item>
</ser:getAnalyticalDeliveryEstimatesRequest>
</soapenv:Body>
</soapenv:Envelope>';
$xml = simplexml_load_string($xml_string, null, null, 'http://schemas.xmlsoap.org/soap/envelope/');
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['soapenv']);
foreach($soap->Body as $nodes) {
$ser = $nodes->children($ns['ser'])->getAnalyticalDeliveryEstimatesRequest;
foreach($ser->buyer as $sub_nodes) { // this can also be ->item as well

}
}
1

Другие решения

Во-первых, в вашем примере кода вы на самом деле не определили $node в любом месте:

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
print_r($node);

Должно быть:

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
$node = $xpath[0];
print_r($node);

Или возможно:

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
print_r($node);
}

Во-вторых, print_r не очень хорош при отображении объектов SimpleXML. Это дает вам пустой вывод не означает, что элемент пуст.

Например, попробуйте повторить имя найденного узла (демонстрация):

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
echo $node->getName();
}

Чтобы получить его содержимое, вам нужно выбрать пространство имен, в котором они находятся, ->children() метод, в какой момент даже print_r сможет их увидеть (хотя есть и другие причины не полагаться на него целиком) (демонстрация):

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
print_r( $node->children('http://www.example.com/v1/services') );
}

Попробуйте поискать «SimpleXML с пространствами имен» для большего количества примеров.

2

По вопросам рекламы [email protected]