Xml get error code: примеры (PHP)

Полное руководство по xml_get_error_code с практическими примерами
Раздел: XML
xml_get_error_code(resource parser): int|false

Функция xml_get_error_code() возвращает числовой код ошибки XML-парсера. Она применяется при обработке XML-данных для определения типа произошедшей ошибки во время разбора документа.

Когда используется функция

Функция используется совместно с XML-парсером Expat в ситуациях, требующих обработки ошибок парсинга. Типичные сценарии включают валидацию XML-документов, обработку пользовательского ввода в XML-формате, отладку парсеров и создание систем обработки исключений для XML-данных.

Аргументы функции

Функция принимает один обязательный параметр:

  • parser - ресурс XML-парсера, созданный функцией xml_parser_create()

Функция возвращает целочисленный код ошибки или FALSE в случае неудачи.

Базовые примеры использования
Простой пример с ошибкой парсинга
<?php
$xml_parser = xml_parser_create();
$xml_data = '<root><item>text</item>';

if (!xml_parse($xml_parser, $xml_data, true)) {
    $error_code = xml_get_error_code($xml_parser);
    echo "Код ошибки: $error_code\n";
    echo "Текст ошибки: " . xml_error_string($error_code);
}

xml_parser_free($xml_parser);
?>
Код ошибки: 5
Текст ошибки: Mismatched tag
Пример с обработкой разных ошибок
<?php
$parser = xml_parser_create();

$invalid_xml = '<document><section></wrong_tag></document>';

if (!xml_parse($parser, $invalid_xml, true)) {
    $code = xml_get_error_code($parser);
    
    switch ($code) {
        case XML_ERROR_TAG_MISMATCH:
            echo "Найдена ошибка несоответствия тегов";
            break;
        case XML_ERROR_SYNTAX:
            echo "Обнаружена синтаксическая ошибка";
            break;
        default:
            echo "Неизвестная ошибка: $code";
    }
}

xml_parser_free($parser);
?>
Найдена ошибка несоответствия тегов
Альтернативные функции в PHP

Для работы с XML в PHP доступны несколько альтернативных подходов:

DOMDocument

Класс DOMDocument предоставляет более современный объектно-ориентированный интерфейс для работы с XML. Он включает методы для обработки ошибок через исключения и внутренние свойства.

SimpleXML

SimpleXML преобразует XML-документ в объект, что упрощает доступ к данным. Ошибки обычно обрабатываются через libxml_get_errors().

XMLReader

XMLReader реализует потоковый парсер, эффективный для обработки больших XML-файлов. Использует стандартные методы обработки ошибок PHP.

Выбор зависит от конкретной задачи: xml_get_error_code подходит для низкоуровневой работы с Expat, тогда как DOMDocument и SimpleXML предпочтительны для манипуляций с XML-структурами, а XMLReader - для обработки больших файлов.

Аналоги в других языках программирования
Python: xml.parsers.expat
import xml.parsers.expat

def handle_error(code, message):
    print(f"Код ошибки: {code}")
    print(f"Сообщение: {message}")

parser = xml.parsers.expat.ParserCreate()
parser.ErrorHandler = handle_error

# Некорректный XML
xml_data = '<root><item>text'  
try:
    parser.Parse(xml_data, True)
except Exception as e:
    print(f"Исключение: {e}")
JavaScript: DOMParser
const parser = new DOMParser();
const xmlString = '<root><item>text</root>';
const xmlDoc = parser.parseFromString(xmlString, "text/xml");

const errorNodes = xmlDoc.querySelectorAll("parsererror");
if (errorNodes.length > 0) {
    console.log("Обнаружена ошибка парсинга");
    console.log(errorNodes[0].textContent);
} else {
    console.log("XML корректен");
}
MySQL: ExtractValue
-- MySQL имеет ограниченную поддержку XML
SELECT ExtractValue('<root><item>text</item></root>', '/root/item');
-- В случае ошибки возвращается NULL или сообщение об ошибке

Основное отличие PHP-функции заключается в необходимости явного вызова xml_get_error_code после неудачного парсинга, тогда как в Python и JavaScript ошибки часто обрабатываются через исключения или специальные объекты.

Типичные ошибки
Использование освобожденного парсера
<?php
$parser = xml_parser_create();
xml_parser_free($parser);

$error_code = xml_get_error_code($parser); // Неверно
var_dump($error_code);
?>
Warning: xml_get_error_code(): supplied argument is not a valid XML Parser resource
bool(false)
Отсутствие проверки результата xml_parse
<?php
$parser = xml_parser_create();
$xml_data = '<root><item>text</item></root>';

xml_parse($parser, $xml_data, true); // Успешный парсинг

// Ошибочный вызов - нет ошибки для получения
$error_code = xml_get_error_code($parser);
echo "Код ошибки: $error_code"; // Выведет 0
?>
Код ошибки: 0
Некорректная кодировка
<?php
$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);

// XML с несовпадающей кодировкой
$xml_data = '<?xml version="1.0" encoding="ISO-8859-1"?><root>тест</root>';

if (!xml_parse($parser, $xml_data, true)) {
    echo "Ошибка: " . xml_error_string(xml_get_error_code($parser));
}
?>
Ошибка: Invalid character
Изменения в последних версиях PHP

В PHP 8.0 функция xml_get_error_code() претерпела следующие изменения:

  • Тип параметра parser изменен с resource на XMLParser object
  • Усилена строгая типизация - передача некорректного типа вызывает TypeError
  • Улучшены сообщения об ошибках при передаче невалидного парсера

Пример совместимости с PHP 8:

<?php
// PHP 8: парсер является объектом
$parser = xml_parser_create();
var_dump($parser); // object(XMLParser)#1

// Работа функции остается прежней
$xml_data = '<root><item>text';
if (!xml_parse($parser, $xml_data, true)) {
    $code = xml_get_error_code($parser);
    echo "Код ошибки: $code";
}
?>
Расширенные примеры использования
Кастомный обработчик ошибок с детальной информацией
Пример php
<?php
class XmlErrorHandler {
    private $errors = [];
    
    public function parseXML($xml_string) {
        $parser = xml_parser_create();
        xml_set_element_handler($parser, null, null);
        
        if (!xml_parse($parser, $xml_string, true)) {
            $this->errors[] = [
                'code' => xml_get_error_code($parser),
                'message' => xml_error_string(xml_get_error_code($parser)),
                'line' => xml_get_current_line_number($parser),
                'column' => xml_get_current_column_number($parser)
            ];
        }
        
        xml_parser_free($parser);
        return empty($this->errors);
    }
    
    public function getErrors() {
        return $this->errors;
    }
}

$handler = new XmlErrorHandler();
$xml = '<root><item>Text<item></root>';

if (!$handler->parseXML($xml)) {
    foreach ($handler->getErrors() as $error) {
        echo "Ошибка {$error['code']}: {$error['message']} на строке {$error['line']}\n";
    }
}
?>
Ошибка 5: Mismatched tag на строке 1
Пакетная обработка с накоплением ошибок
Пример php
<?php
function validateXMLFiles($files) {
    $results = [];
    
    foreach ($files as $file) {
        $parser = xml_parser_create();
        $content = file_get_contents($file);
        
        if ($content === false) {
            $results[$file] = 'Ошибка чтения файла';
            continue;
        }
        
        if (!xml_parse($parser, $content, true)) {
            $error_code = xml_get_error_code($parser);
            $results[$file] = [
                'valid' => false,
                'error_code' => $error_code,
                'error_text' => xml_error_string($error_code),
                'line' => xml_get_current_line_number($parser)
            ];
        } else {
            $results[$file] = ['valid' => true];
        }
        
        xml_parser_free($parser);
    }
    
    return $results;
}

$files = ['file1.xml', 'file2.xml'];
$results = validateXMLFiles($files);
print_r($results);
?>
Интеграция с пользовательскими обработчиками элементов
Пример php
<?php
$parser = xml_parser_create();
$error_info = null;

xml_set_element_handler($parser, 
    function($parser, $name, $attrs) {
        // Проверка атрибутов элемента
        if ($name === 'item' && !isset($attrs['id'])) {
            // Создание искусственной ошибки
            trigger_error("Элемент item требует атрибут id", E_USER_WARNING);
        }
    },
    null
);

$xml = '<root><item name="test">Content</item></root>';

// Основной парсинг
if (!xml_parse($parser, $xml, true)) {
    $error_info = [
        'code' => xml_get_error_code($parser),
        'text' => xml_error_string(xml_get_error_code($parser))
    ];
}

// Дополнительная проверка пользовательских условий
if (!$error_info) {
    $errors = error_get_last();
    if ($errors && $errors['type'] === E_USER_WARNING) {
        echo "Пользовательская ошибка: {$errors['message']}";
    }
}

xml_parser_free($parser);
?>
Пользовательская ошибка: Элемент item требует атрибут id
Обработка больших XML-потоков
Пример php
<?php
function parseLargeXML($file_path) {
    $parser = xml_parser_create();
    $fp = fopen($file_path, 'r');
    $chunk_size = 4096;
    $is_final = false;
    
    while (!feof($fp)) {
        $chunk = fread($fp, $chunk_size);
        $is_final = feof($fp);
        
        if (!xml_parse($parser, $chunk, $is_final)) {
            $error_code = xml_get_error_code($parser);
            echo "Ошибка в потоковом парсинге: " . 
                 xml_error_string($error_code) . 
                 " на позиции " . ftell($fp) . "\n";
            break;
        }
    }
    
    fclose($fp);
    xml_parser_free($parser);
    
    return $is_final && $error_code === 0;
}

// Имитация работы с большим файлом
$result = parseLargeXML('large_data.xml');
echo $result ? 'Парсинг успешен' : 'Обнаружены ошибки';
?>

PHP xml_get_error_code function comments

En
Xml get error code Get XML parser error code