W3docs

xml_parse()

A função xml_parse() é uma função interna do PHP que analisa dados XML com um parser de estilo SAX, ideal para arquivos grandes.

O que é xml_parse()?

A função xml_parse() é uma função interna do PHP que analisa dados XML. Ela pertence à extensão XML Parser do PHP e implementa um parser de streaming no estilo SAX (Simple API for XML). Ao contrário dos parsers baseados em árvore, ela processa o XML sequencialmente, disparando funções de callback à medida que encontra elementos, atributos e dados de caractere. Isso a torna altamente eficiente para analisar arquivos XML grandes sem carregar o documento inteiro na memória.

A função xml_parse() é útil quando você precisa analisar dados XML em PHP, por exemplo, para extrair dados de um arquivo XML, transformar dados XML em outro formato ou processar streams XML em tempo real.

Sintaxe

A sintaxe da função xml_parse() é a seguinte:

xml_parse($parser, $data, $is_final = false): int

Parâmetros

  • $parser — o handle do parser XML retornado por xml_parser_create(). É o objeto que mantém o estado do parsing.
  • $data — um trecho (ou todo) o texto XML a ser enviado ao parser.
  • $is_final — defina como true quando você passar o último trecho de dados. Enquanto for false, o parser mantém seu estado para que você possa chamar xml_parse() novamente com o próximo trecho.

Valor de retorno

xml_parse() retorna 1 (verdadeiro) em caso de sucesso e 0 (falso) em caso de falha. Ela não retorna os dados analisados — o conteúdo processado é entregue aos callbacks de handler que você registrou. Quando retorna 0, inspecione o erro com xml_get_error_code() e xml_error_string().

Exemplos de Uso

Veja alguns exemplos práticos de uso de xml_parse() em PHP.

Exemplo 1: Analisando XML com Handlers de Eventos

xml_parse() é um parser SAX: ele não constrói um documento para você, ele dispara eventos. Para obter qualquer saída você deve registrar funções de handler. O exemplo abaixo usa uma string XML inline, portanto funciona como está, sem arquivo externo:

<?php
$xml = <<<XML
<?xml version="1.0"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
</note>
XML;

$parser = xml_parser_create();
// Keep element names in their original case instead of upper-casing them.
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);

xml_set_element_handler(
    $parser,
    fn($p, $name, $attrs) => print("Start: $name\n"),
    fn($p, $name)         => print("End:   $name\n")
);
xml_set_character_data_handler($parser, function ($p, $data) {
    $data = trim($data);
    if ($data !== "") {
        echo "Text:  $data\n";
    }
});

if (!xml_parse($parser, $xml, true)) {
    $code = xml_get_error_code($parser);
    echo "Error: " . xml_error_string($code)
       . " at line " . xml_get_current_line_number($parser);
}

xml_parser_free($parser);

Isso imprime:

Start: note
Start: to
Text:  Tove
End:   to
Start: from
Text:  Jani
End:   from
End:   note

O parser percorre o documento de cima para baixo e chama seus handlers de início de elemento, dados de caractere e fim de elemento na ordem do documento. Registramos eles com xml_set_element_handler() e xml_set_character_data_handler(), passamos tudo em uma única chamada ($is_final = true) e liberamos o parser com xml_parser_free().

Exemplo 2: Analisando um arquivo ou stream de dados em trechos

A verdadeira força de xml_parse() é o parsing incremental: alimente o documento aos poucos para que mesmo um arquivo de vários gigabytes nunca precise caber na memória. Passe $is_final = false para cada trecho exceto o último:

<?php
$parser = xml_parser_create();
xml_set_element_handler(
    $parser,
    fn($p, $name, $attrs) => print("<$name>\n"),
    fn($p, $name)         => print("</$name>\n")
);

$handle = fopen("data.xml", "r");          // or php://stdin for a stream
while (($chunk = fread($handle, 4096)) !== false) {
    $isFinal = feof($handle);
    if (!xml_parse($parser, $chunk, $isFinal)) {
        $code = xml_get_error_code($parser);
        echo "XML error: " . xml_error_string($code)
           . " at line " . xml_get_current_line_number($parser);
        break;
    }
    if ($isFinal) {
        break;
    }
}
fclose($handle);
xml_parser_free($parser);

Como o parser mantém seu estado entre as chamadas, um elemento pode começar em um trecho e terminar em outro — xml_parse() une os eventos corretamente. É isso que torna a função adequada para arquivos XML grandes onde uma abordagem baseada em árvore como o SimpleXML esgotaria a memória.

Exemplo 3 (referência): analisando um arquivo de uma só vez

Se seu XML é pequeno o suficiente para caber na memória, você pode lê-lo com file_get_contents() e passar a string inteira para xml_parse() em uma única chamada. Os handlers também podem ser funções nomeadas (nomes como string) em vez de closures:

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

// Define handler functions
function startElement($parser, $name, $attrs) {
    echo "Start element: $name\n";
}
function endElement($parser, $name) {
    echo "End element: $name\n";
}
function characterData($parser, $data) {
    echo "Data: $data\n";
}

// Set handlers
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");

$xml_data = file_get_contents("data.xml");
if (!xml_parse($xml_parser, $xml_data, true)) {
    $error_message = xml_error_string(xml_get_error_code($xml_parser));
    $error_line = xml_get_current_line_number($xml_parser);
    echo "XML Parsing Error: $error_message at line $error_line";
}
xml_parser_free($xml_parser);

Este código cria um parser XML usando xml_parser_create() e define uma opção para desativar o case folding. Em seguida, define três funções de callback: startElement() para tags de abertura, endElement() para tags de fechamento e characterData() para conteúdo de texto. Esses handlers são registrados usando xml_set_element_handler() e xml_set_character_data_handler().

O script lê "data.xml" e o passa para xml_parse(). À medida que o parser percorre o XML, ele chama automaticamente os handlers registrados. Se ocorrer um erro durante o parsing, o código recupera o código e a mensagem de erro usando xml_get_error_code() e xml_error_string(), e exibe um erro descritivo. Por fim, libera a memória do parser com xml_parser_free().

Armadilhas comuns

  • Sem handlers, sem saída. xml_parse() só dispara os callbacks que você registrou. Sem handlers definidos, ela analisa com sucesso, mas não faz nada visível.
  • Dados de caractere chegam em partes. Um único nó de texto pode acionar xml_set_character_data_handler mais de uma vez (por exemplo, em torno de referências de entidade), então acumule o texto em um buffer em vez de presumir que você recebe tudo de uma vez.
  • Espaços em branco contam como dados de caractere. Indentação entre tags dispara o handler de dados de caractere. Use trim() (como no Exemplo 1) se você se preocupa apenas com texto real.
  • Sempre libere o parser. Chame xml_parser_free() quando terminar; no PHP 8+ o handle é um objeto XMLParser que é coletado pelo garbage collector, mas liberar explicitamente mantém a memória sob controle em scripts de longa duração.

Funções relacionadas

Conclusão

A função xml_parse() do PHP é o motor da extensão XML Parser no estilo SAX. Em vez de retornar um documento, ela percorre o XML em streaming e dispara os handlers que você registrou, retornando 1 em caso de sucesso e 0 em caso de falha. Seu parâmetro $is_final permite analisar dados em trechos, o que a mantém eficiente em termos de memória mesmo em arquivos enormes. Combine-a com xml_parser_create(), as funções de configuração de handlers e xml_parser_free(), e você terá uma maneira rápida e de baixo consumo de memória para processar XML em PHP.

Prática

Prática
O que é XML Parser em PHP?
O que é XML Parser em PHP?
Was this page helpful?