Розбір XML-елементів з динамічним префіксом імен імен у PHP

У мене є такий xml (ви можете сказати SOAP-запит):


    
        
            223423
        
    

Я використовую такий код, і він працює нормально:

<?php 
$myRequest ='
   
      
         223423
      
   
   ';
$xml = simplexml_load_string($myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$namespaces = $xml->getNameSpaces(true);

$soapHeader = $xml->children($namespaces['SOAPENV'])->Header;
$myHeader = $soapHeader->children($namespaces['NS'])->myHeader;
echo (string)$myHeader->SourceID;
?>

Проблема

Я знаю префікс (SOAPENV + NS), але клієнти можуть змінити префікс на все, що вони хочуть, щоб вони могли надсилати мені документ xml, який має префікси MY-SOAPENV + MY-NS.

Мій питання

Як я можу усунути це, оскільки префікси простору імен не статичні, як я можу його проаналізувати?

Дякую

1
@Як ви маєте рацію, я просто перейшов на DOM
додано Автор Abdullah, джерело
Так, префікси можуть бути змінені. І ні, це не проблема. Оскільки фактичне поле імен визначається URI, який не змінюється.
додано Автор hakre, джерело
Простори імен визначаються uri, а не псевдонімами. Я не впевнений в простоxml, але DomDocument може справлятися з цим просто добре.
додано Автор Ja͢ck, джерело

6 Відповіді

Ось інший шлях. Ми можемо динамічно аналізувати дані наступним чином.

$myRequest ='
           
              
                 223423
              
           
           ';


$xml        = simplexml_load_string(
    $myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/"
);
$namespaces = $xml->getNameSpaces(true);
$prefix     = array_keys($namespaces);//we getting all namespaces here. According 
                                      //to that we can find datas.
$soapHeader = $xml->children($namespaces[$prefix[0]])->Header;
$myHeader   = $soapHeader->children($namespaces[$prefix[1]])->myHeader;
echo (string)$myHeader->SourceID;
5
додано
Спасибі @ Ніл, я застосував це, і це добре працює, я ціную вашу допомогу.
додано Автор Abdullah, джерело

Ось інший шлях. Ми можемо динамічно аналізувати дані наступним чином.

$myRequest ='
           
              
                 223423
              
           
           ';


$xml        = simplexml_load_string(
    $myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/"
);
$namespaces = $xml->getNameSpaces(true);
$prefix     = array_keys($namespaces);//we getting all namespaces here. According 
                                      //to that we can find datas.
$soapHeader = $xml->children($namespaces[$prefix[0]])->Header;
$myHeader   = $soapHeader->children($namespaces[$prefix[1]])->myHeader;
echo (string)$myHeader->SourceID;
5
додано
Спасибі @ Ніл, я застосував це, і це добре працює, я ціную вашу допомогу.
додано Автор Abdullah, джерело

Ось інший шлях. Ми можемо динамічно аналізувати дані наступним чином.

$myRequest ='
           
              
                 223423
              
           
           ';


$xml        = simplexml_load_string(
    $myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/"
);
$namespaces = $xml->getNameSpaces(true);
$prefix     = array_keys($namespaces);//we getting all namespaces here. According 
                                      //to that we can find datas.
$soapHeader = $xml->children($namespaces[$prefix[0]])->Header;
$myHeader   = $soapHeader->children($namespaces[$prefix[1]])->myHeader;
echo (string)$myHeader->SourceID;
5
додано
Спасибі @ Ніл, я застосував це, і це добре працює, я ціную вашу допомогу.
додано Автор Abdullah, джерело

Ви повинні використовувати DOM - особисто я вважаю, що це справедливо для загального випадку, оскільки "просто xml "є оксюморон, але я знаю, що інші не погоджуються. Це, безумовно, вірно при роботі з складним деревом документів, таким як SOAP.

DOM забезпечує getElementsByTagNameNS() (та інші відповідні методи NS-targeting), які дозволяють Ви повинні вказати простір імен URI (тобто те, що повинно залишатися статичним і бути відомим заздалегідь), а не конкретно про префікс.

$soapNsUri = 'http://schemas.xmlsoap.org/soap/envelope/';
$myNsUri = 'http://xyz.gov/headerschema';

$doc = new DOMDocument;
$doc->loadXML($myRequest);

$header = $doc->getElementsByTagNameNS($soapNsUri, 'Header')->item(0);
$myHeader = $header->getElementsByTagNameNS($myNsUri, 'myHeader')->item(0);
$sourceID = $myHeader->getElementsByTagNameNS($myNsUri, 'SourceID')->item(0);

echo $sourceID->firstChild->data;

Подивіться, що він працює

3
додано
Дякую, @Dave, саме те, що я шукав +1
додано Автор Abdullah, джерело

Ви повинні використовувати DOM - особисто я вважаю, що це справедливо для загального випадку, оскільки "просто xml "є оксюморон, але я знаю, що інші не погоджуються. Це, безумовно, вірно при роботі з складним деревом документів, таким як SOAP.

DOM забезпечує getElementsByTagNameNS() (та інші відповідні методи NS-targeting), які дозволяють Ви повинні вказати простір імен URI (тобто те, що повинно залишатися статичним і бути відомим заздалегідь), а не конкретно про префікс.

$soapNsUri = 'http://schemas.xmlsoap.org/soap/envelope/';
$myNsUri = 'http://xyz.gov/headerschema';

$doc = new DOMDocument;
$doc->loadXML($myRequest);

$header = $doc->getElementsByTagNameNS($soapNsUri, 'Header')->item(0);
$myHeader = $header->getElementsByTagNameNS($myNsUri, 'myHeader')->item(0);
$sourceID = $myHeader->getElementsByTagNameNS($myNsUri, 'SourceID')->item(0);

echo $sourceID->firstChild->data;

Подивіться, що він працює

3
додано
Дякую, @Dave, саме те, що я шукав +1
додано Автор Abdullah, джерело

Ви повинні використовувати DOM - особисто я вважаю, що це справедливо для загального випадку, оскільки "просто xml "є оксюморон, але я знаю, що інші не погоджуються. Це, безумовно, вірно при роботі з складним деревом документів, таким як SOAP.

DOM забезпечує getElementsByTagNameNS() (та інші відповідні методи NS-targeting), які дозволяють Ви повинні вказати простір імен URI (тобто те, що повинно залишатися статичним і бути відомим заздалегідь), а не конкретно про префікс.

$soapNsUri = 'http://schemas.xmlsoap.org/soap/envelope/';
$myNsUri = 'http://xyz.gov/headerschema';

$doc = new DOMDocument;
$doc->loadXML($myRequest);

$header = $doc->getElementsByTagNameNS($soapNsUri, 'Header')->item(0);
$myHeader = $header->getElementsByTagNameNS($myNsUri, 'myHeader')->item(0);
$sourceID = $myHeader->getElementsByTagNameNS($myNsUri, 'SourceID')->item(0);

echo $sourceID->firstChild->data;

Подивіться, що він працює

3
додано
Дякую, @Dave, саме те, що я шукав +1
додано Автор Abdullah, джерело
Ukrainian PHP comunity
Ukrainian PHP comunity
885 учасників

dev-ua/php