How to extract a piece of an xml using PHP?

0

How can I capture / return everything between the <*:Body> and </*:Body> tags using PHP so that it does not matter how many lines exist before or after both tags?

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ConsultarRequest>
   <Cliente>
    <sistema>XPTO</sistema>
   </Cliente>
   <numDDD>xx</numDDD>
   <numTerminal>xxxxxxxx</numTerminal>
  </ConsultarRequest>
 </soapenv:Body>
</soapenv:Envelope>

The end result I hope is:

  <ConsultarRequest>
   <Cliente>
    <sistema>XPTO</sistema>
   </Cliente>
   <numDDD>xx</numDDD>
   <numTerminal>xxxxxxxx</numTerminal>
  </ConsultarRequest>

Important : XML has a variable structure. In some cases inside the body there can be several values at the same level. Optionally I would like to do this via regex, range tags <soapenv:body> and </soapenv:body> .

    
asked by anonymous 13.08.2018 / 16:40

1 answer

4

Do not use RegEx for this, is not going to work, but if anything changes in SOAP xml you will have to maintain your regex for sure, and until maintenance happens all will be broken.

What you can (and should preferably) use is DOMDocument + DOMXapth (or other DOM APIs for PHP), example that will solve your case:

<?php

$xml = '<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ConsultarRequest>
   <Cliente>
    <sistema>XPTO</sistema>
   </Cliente>
   <numDDD>xx</numDDD>
   <numTerminal>xxxxxxxx</numTerminal>
  </ConsultarRequest>
 </soapenv:Body>
</soapenv:Envelope>';

$encontrou = false;

$doc = new DOMDocument;
$doc->loadxml($xml);

$xpath = new DOMXpath($doc);

//Registrado o namespace para que a query funcione com ele
$xpath->registerNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');

//O '//' busca o elemento <soapenv:Body> em QUALQUER parte do documento
$elementos = $xpath->query("//soapenv:Body");

//Verifica se retornou pelo menos um elemento
if ($elementos) {
    //Dentro <soapenv:Body> pega o primeiro elemento, que no seu exemplo é o '<ConsultarRequest>', mas pode variar dependendo da resposta
    $node = $elementos[0]->getElementsByTagName('*')->item(0);

    //Se encontrar um elemento então entra na IF
    if ($node) {
        $encontrou = true;

        //Pega o conteudo do primeiro elemento, incluindo ele, e transforma em uma string
        $html = $node->ownerDocument->saveHTML( $node );

        echo 'Resultado:<br>';
        echo htmlentities($html); //O htmlentities é somente para você visualizar no navegador, ele é dispensável
    }
}

if (!$encontrou) {
    echo 'não foram encontrados elementos';
}

If you are going to manipulate / read data from <ConsultarRequest> , you may not need to convert it to string, nor will it need the string at all, the DOMNode and DOMXpath will solve all your problems, for example:

<?php

$xml = '<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ConsultarRequest>
   <Cliente>
    <sistema>XPTO</sistema>
   </Cliente>
   <numDDD>xx</numDDD>
   <numTerminal>xxxxxxxx</numTerminal>
  </ConsultarRequest>
 </soapenv:Body>
</soapenv:Envelope>';

$encontrou = false;

$doc = new DOMDocument;
$doc->loadxml($xml);

$xpath = new DOMXpath($doc);

$sistema = $xpath->query("//ConsultarRequest/Cliente/sistema");
$ddd = $xpath->query("//ConsultarRequest/numDDD");
$terminal = $xpath->query("//ConsultarRequest/numTerminal");

echo 'Sistema: ', $sistema[0]->nodeValue, '<br>';
echo 'ddd: ', $ddd[0]->nodeValue, '<br>';
echo 'Terminal: ', $terminal[0]->nodeValue, '<hr>';
    
13.08.2018 / 17:17