PHP simpleXML: обработка неизвестных пространств имен в запросах SOAP - PullRequest
4 голосов
/ 26 января 2011

Существует тонна из существующих вопросов о PHP SimpleXML и обработке XML с пространствами имен. Все вопросы, на которые я смотрел, сделали фундаментальное предположение: код заранее знает, какие пространства имен будут включены во входящий SOAP-запрос. В моем случае я видел несогласованные пространства имен в запросах SOAP.

В частности, я работал над реализацией веб-службы для общения с Quickbooks Web Connector (pdf), и некоторые примеры запросов, которые я видел, выглядят так:

<soapenv:Envelope 
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:dev="http://developer.intuit.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <dev:authenticate>
         <dev:strUserName>username</dev:strUserName>
         <dev:strPassword>password</dev:strPassword>
      </dev:authenticate>
   </soapenv:Body>
</soapenv:Envelope>

... а некоторые выглядят так:

<s11:Envelope 
 xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/' 
 xmlns:ns1='http://developer.intuit.com/'>
  <s11:Header/>
  <s11:Body>
    <ns1:authenticate>
      <ns1:strUserName>username</ns1:strUserName>
      <ns1:strPassword>password</ns1:strPassword>
    </ns1:authenticate>
  </s11:Body>
</s11:Envelope>

... или это:

<SOAP-ENV:Envelope 
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:ns1="http://developer.intuit.com/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns1:authenticate>
         <ns1:strUserName>username</ns1:strUserName>
         <ns1:strPassword>password</ns1:strPassword>
      </ns1:authenticate>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Я понимаю, что использование xpath () для выбора элементов, но это предполагает, что вы знаете, в каком пространстве имен искать. Без какой-либо согласованности в пространстве имен, мне трудно понять, как правильно и программно выбрать содержимое узел для обработки.

Пространство имен совершенно не имеет значения в этом приложении - могу ли я просто запустить необработанный XML через регулярное выражение, чтобы сначала удалить whatever: из <whatever:mytag>?

Ответы [ 2 ]

5 голосов
/ 27 января 2011

Прежде всего, если вы планируете много использовать SOAP, вы можете взглянуть на расширение PHP SOAP , если вы еще этого не сделали. Я никогда этим не пользовался.

Возвращаясь к вашему вопросу, вы сказали «В моем случае я видел несогласованные пространства имен в запросах SOAP». Приготовьтесь, потому что я собираюсь взорвать ваше мнение: нет, у вас нет. :)

В этих трех примерах два пространства имен одинаковы: есть http://schemas.xmlsoap.org/soap/envelope/ и есть http://developer.intuit.com/ - отличается здесь их префикс . Хорошей новостью является то, что префикс не имеет большого значения. Рассматривайте это как псевдоним пространства имен. Префиксы, используемые в документе, автоматически регистрируются для использования в XPath, но вы также можете зарегистрировать свои собственные.

Вот пример того, как использовать префиксы, которые были определены в документе (хорошо, если вы уже знаете, какие они есть) или зарегистрировать свои собственные префиксы и использовать их.

$xml = '<soapenv:Envelope 
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:dev="http://developer.intuit.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <dev:authenticate>
         <dev:strUserName>username</dev:strUserName>
         <dev:strPassword>password</dev:strPassword>
      </dev:authenticate>
   </soapenv:Body>
</soapenv:Envelope>';

$Envelope = simplexml_load_string($xml);

// you can register and use your own prefixes
$Envelope->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
$Envelope->registerXPathNamespace('auth', 'http://developer.intuit.com/');

$nodes = $Envelope->xpath('/soap:Envelope/soap:Body/auth:authenticate/auth:strUserName');
$username = (string) $nodes[0];

// or you can use the prefixes that are already defined in the document
$nodes = $Envelope->xpath('/soapenv:Envelope/soapenv:Body/dev:authenticate/dev:strPassword');
$password = (string) $nodes[0];

var_dump($username, $password);
1 голос
/ 26 января 2011

Существует несколько полезных методов элемента simplexml, которые помогут вам определить и использовать правильные пространства имен при запросах с помощью метода xpath.Первые два getNamespaces и getDocNamespaces.getNamespaces вернет все пространства имен, использованные в документе (укажите рекурсивный параметр), а getDocNamespaces вернет все пространства имен, объявленные документом.

Как только у вас будет доступный массив пространств имен, вы можете использовать registerXPathNamespace для регистрациикаждое пространство имен для симплексного_элемента, который вы собираетесь использовать метод xpath.

Я новый пользователь, поэтому я не могу публиковать ссылки на другие методы в документации php.

...