xml_set_external_entity_ref_handler()
A função xml_set_external_entity_ref_handler() registra um callback definido pelo usuário para tratar referências a entidades externas em um parser XML SAX.
A função xml_set_external_entity_ref_handler() é uma função nativa do PHP que registra um callback definido pelo usuário para tratar referências a entidades externas em um parser XML SAX (Expat) legado. Uma entidade externa é uma referência dentro de um documento XML — declarada com <!ENTITY name SYSTEM "uri"> — que aponta para conteúdo armazenado fora do documento. Quando o parser encontra tal referência durante a análise, ele invoca seu callback para que você possa decidir o que fazer com ela: ignorá-la, carregar dados aprovados de um banco de dados ou rejeitá-la como parte de uma validação de segurança.
Esta página cobre a sintaxe da função, os parâmetros que o PHP passa para seu callback, o valor de retorno, um exemplo completo executável e as ressalvas de segurança e depreciação que você precisa conhecer antes de usá-la.
Sintaxe
xml_set_external_entity_ref_handler(XMLParser $parser, callable $handler): boolParâmetros
| Parâmetro | Descrição |
|---|---|
$parser | O recurso de parser XML criado com xml_parser_create(). O handler é vinculado a este parser específico. |
$handler | O callback a ser executado em cada referência a entidade externa. Pode ser o nome de uma função (como string) ou — quando xml_set_object() foi utilizado — o nome de um método. Passar uma string vazia remove o handler. |
Valor de retorno
Retorna true em caso de sucesso, ou false em caso de falha (por exemplo, se $parser não for um parser válido).
A assinatura do callback
O PHP chama seu handler com cinco argumentos, nesta ordem:
handler(XMLParser $parser, string $open_entity_names, string $base, string $system_id, ?string $public_id): int$open_entity_names— uma lista separada por espaços das entidades que estão abertas no momento, usada para detectar recursão.$base— a URI base para resolver$system_id(geralmente uma string vazia).$system_id— o identificador de sistema (a URISYSTEM "...") da entidade externa.$public_id— o identificador público, ounullse nenhum foi declarado.
Seu callback deve retornar um valor não nulo (truthy) para manter o parse em andamento. Retornar 0, false ou nada aborta o parse com um erro XML_ERROR_EXTERNAL_ENTITY_HANDLING.
Exemplos de Uso
Vejamos um exemplo prático de uso do xml_set_external_entity_ref_handler() em PHP.
Exemplo: Definindo uma Função Handler para Referência de Entidade Externa
Suponha que você tenha um documento XML que referencia uma entidade externa e deseja inspecionar essa referência enquanto o documento é analisado. Você cria um parser com xml_parser_create(), registra o handler, analisa os dados com xml_parse() e libera o parser com xml_parser_free():
Definindo uma Função Handler para Referência de Entidade Externa em PHP
function handle_external_entity_ref($parser, $open_entity_names, $base, $system_id, $public_id) {
// Inspect — but do NOT blindly load — the external entity.
echo "External entity referenced: {$system_id}\n";
// Return a non-zero value so parsing continues.
return 1;
}
$xml_parser = xml_parser_create();
xml_set_external_entity_ref_handler($xml_parser, "handle_external_entity_ref");
$xml_data = '<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY ext SYSTEM "data.xml">
]>
<root>&ext;</root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);O handler é acionado uma vez para a referência &ext; e imprime:
External entity referenced: data.xmlComo o callback apenas exibe o identificador de sistema e retorna 1, o parser é instruído a continuar sem realmente buscar data.xml — que é exatamente o comportamento seguro padrão que você deseja.
Por que o handler pode nunca ser acionado
Na maioria das versões modernas do PHP, o carregamento de entidades externas é desabilitado no nível do libxml, portanto o parser ignora silenciosamente as referências a entidades e seu callback nunca é chamado. Isso é um endurecimento intencional. Se precisar ativar esse recurso, você o controla globalmente com libxml_disable_entity_loader() — mas para qualquer entrada que não seja confiável e controlada, você deve deixar o carregamento desabilitado.
⚠️ Aviso de Segurança: Tratar entidades externas é um vetor clássico para ataques de XML External Entity (XXE), que podem vazar arquivos locais (
file:///etc/passwd), disparar requisições do lado do servidor ou causar negação de serviço. Nunca resolva$system_idpara buscar URIs arbitrárias ou caminhos locais a partir de entradas não confiáveis. Para análise sensível à segurança, prefira bibliotecas modernas comoDOMDocumentouXMLReadercom o carregamento de entidades desativado.
Nota de depreciação: A partir do PHP 8.4, passar uma string não-callable como handler está depreciado — um nome de função simples que realmente existe ainda funciona, mas uma string não resolvida agora gera um aviso de depreciação. Para código compatível com versões futuras, passe um callable real como uma
Closureou um array[$object, 'method']. A extensão SAX Expat legada como um todo está em modo de manutenção — novos códigos devem preferirXMLReaderouDOMDocument.
Conclusão
Neste artigo, cobrimos a função xml_set_external_entity_ref_handler() do PHP: sua sintaxe, os cinco argumentos que o PHP passa para seu callback, por que o callback deve retornar um valor não nulo para manter o parse ativo e um exemplo completo executável. Também destacamos as duas coisas que costumam confundir as pessoas — o handler frequentemente nunca é acionado porque o carregamento de entidades externas está desabilitado por padrão, e encaminhar entradas não confiáveis por ele abre a porta para ataques XXE. Use-o apenas com entradas confiáveis, prefira um callable real em vez de um nome de string no PHP 8.4+, e use XMLReader ou DOMDocument para qualquer coisa sensível à segurança.
Para handlers SAX relacionados, consulte xml_set_element_handler() e xml_set_object().