Xml get current line number: примеры (PHP)

Примеры применения xml_get_current_line_number для парсинга XML
Раздел: XML
xml_get_current_line_number(resource parser): int|false

Функция xml_get_current_line_number() является частью XML Parser в PHP. Она возвращает номер текущей строки в процессе парсинга XML документа. Данная функция используется при обработке и анализе XML для отслеживания позиции ошибок, отладки или логирования.

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

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

  • parser (resource) — ссылка на XML парсер, созданный функцией xml_parser_create() или её вариациями. Это ресурс, представляющий парсер, для которого требуется получить текущий номер строки.

Возвращаемое значение — целое число (int), представляющее номер строки. Если передан некорректный ресурс парсера, функция вернет false.

Примеры использования

Рассмотрим базовые примеры получения номера строки во время парсинга.

Пример 1: Простой парсинг
<?
$xml = "\n Text\n";
$parser = xml_parser_create();

// Устанавливаем обработчик
xml_set_element_handler($parser, function($parser, $name, $attrs) {
    $line = xml_get_current_line_number($parser);
    echo "Элемент: $name, Строка: $line\n";
}, function($parser, $name) {});

xml_parse($parser, $xml);
xml_parser_free($parser);
?>
Элемент: ROOT, Строка: 1
Элемент: ITEM, Строка: 2
Пример 2: Получение номера строки при ошибке
<?
$xml = "\n Text\n \n"; // Незакрытый тег
$parser = xml_parser_create();

xml_set_element_handler($parser, function(){}, function(){});
if (!xml_parse($parser, $xml, true)) {
    $errorLine = xml_get_current_line_number($parser);
    echo "Ошибка в строке: $errorLine\n";
    echo "Причина: " . xml_error_string(xml_get_error_code($parser));
}
xml_parser_free($parser);
?>
Ошибка в строке: 4
Причина: mismatched tag
Похожие функции в PHP

В расширении XML Parser существуют другие функции для получения позиции во время разбора:

  • xml_get_current_column_number() — Возвращает номер текущего столбца (символа в строке). Полезна для точного указания места ошибки.
  • xml_get_current_byte_index() — Возвращает текущий индекс байта от начала данных. Может быть использована для расчета смещения.

Эти функции часто используются вместе с xml_get_current_line_number() для детального отчета об ошибках. При работе с более современными расширениями, такими как DOMDocument или SimpleXML, получение номера строки осуществляется через обработку исключений (DOMException), которые могут содержать информацию о месте ошибки, но не предоставляют прямой функции для текущей строки во время чтения.

Аналоги в других языках

Python (xml.sax): В SAX-парсере Python номер строки и столбца доступны через атрибуты Locator.

import xml.sax

class MyHandler(xml.sax.ContentHandler):
    def setDocumentLocator(self, locator):
        self.locator = locator
    def startElement(self, name, attrs):
        line = self.locator.getLineNumber()
        print(f'Элемент: {name}, Строка: {line}')

parser = xml.sax.make_parser()
handler = MyHandler()
parser.setContentHandler(handler)
parser.parse('data.xml')

Отличие: В Python информация о местоположении доступна через отдельный объект, а не через глобальную функцию.

JavaScript (DOMParser): Нативный DOMParser в браузере не предоставляет информацию о номере строки при ошибке. Для этого требуется использовать сторонние парсеры или предварительную валидацию.

MySQL: Не имеет прямого аналога, так как не предназначен для парсинга XML в реальном времени с отслеживанием позиции.

Типичные ошибки
1. Передача неверного ресурса парсера
<?
$line = xml_get_current_line_number('not_a_parser');
var_dump($line);
?>
Warning: xml_get_current_line_number() expects parameter 1 to be resource, string given
bool(false)
2. Вызов функции до начала парсинга или после освобождения парсера
<?
$parser = xml_parser_create();
// Парсинг еще не начался
$line = xml_get_current_line_number($parser);
echo "До парсинга: $line\n"; // Может вернуть 1 или 0

xml_parser_free($parser);
$line2 = xml_get_current_line_number($parser); // Ресурс уже освобожден
?>
До парсинга: 1
Warning: xml_get_current_line_number(): supplied resource is not a valid XML Parser resource
3. Ожидание корректного номера строки при некорректном XML

Функция возвращает последнюю обработанную строку. В случае фатальной ошибки парсинга, это может быть не та строка, где ошибка началась, а последняя успешно обработанная.

Изменения в версиях PHP

Функция xml_get_current_line_number() была представлена в PHP 4. С тех пор её сигнатура и поведение оставались стабильными. В PHP 8.0 был изменен тип ошибки при передаче некорректного ресурса: теперь вместо предупреждения (E_WARNING) и возврата false выбрасывается исключение TypeError. Однако, ресурс XML парсера по-прежнему является корректным типом для функции.

<?
// PHP 8.x
$parser = xml_parser_create();
xml_parser_free($parser);
try {
    $line = xml_get_current_line_number($parser);
} catch (TypeError $e) {
    echo "Ошибка типа: " . $e->getMessage();
}
?>
Ошибка типа: xml_get_current_line_number(): supplied resource is not a valid XML Parser resource
Расширенные примеры
Пример 1: Логирование структуры с номерами строк
Пример php
<?
$xml = <<
  
    PHP 8
    Автор 1
  
  
    XML Guide
  

XML;

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

$depth = 0;
xml_set_element_handler($parser,
    function($parser, $name, $attrs) use (&$depth) {
        $line = xml_get_current_line_number($parser);
        echo str_repeat('  ', $depth) . "[$line] <$name>\n";
        $depth++;
    },
    function($parser, $name) use (&$depth) {
        $depth--;
        $line = xml_get_current_line_number($parser);
        echo str_repeat('  ', $depth) . "[$line] </$name>\n";
    }
);

xml_set_character_data_handler($parser, function($parser, $data) {
    $data = trim($data);
    if (!empty($data)) {
        $line = xml_get_current_line_number($parser);
        echo str_repeat('  ', 1) . "[$line] Текст: '$data'\n";
    }
});

xml_parse($parser, $xml);
xml_parser_free($parser);
?>
[1] 
  [2] 
    [3] 
      [3] Текст: 'PHP 8'
    [3] 
    [4] 
      [4] Текст: 'Автор 1'
    [4] 
  [5] 
  [6] 
    [7] 
      [7] Текст: 'XML Guide'
    [7] 
  [8] 
[9] 
Пример 2: Обработка большого файла с прогрессом
Пример php
<?
$parser = xml_parser_create();
xml_set_element_handler($parser, function(){}, function(){});

$stream = fopen('large.xml', 'r');
$chunkSize = 4096;
$totalLinesReported = 0;
while (($data = fread($stream, $chunkSize)) && !feof($stream)) {
    xml_parse($parser, $data, feof($stream));
    $currentLine = xml_get_current_line_number($parser);
    if ($currentLine > $totalLinesReported + 1000) {
        $totalLinesReported = $currentLine;
        echo "Обработано строк: $currentLine\n";
    }
}
fclose($stream);
xml_parser_free($parser);
?>

Вывод будет зависеть от содержимого файла, показывая прогресс каждые 1000 строк.

Пример 3: Интеграция с пользовательским обработчиком ошибок
Пример php
<?
class XmlParserWithDetailedErrors {
    private $parser;
    private $errors = [];

    public function parse($xmlData) {
        $this->parser = xml_parser_create();
        xml_set_object($this->parser, $this);
        xml_set_element_handler($this->parser, 'startElement', 'endElement');
        xml_set_character_data_handler($this->parser, 'cdata');
        
        if (!xml_parse($this->parser, $xmlData, true)) {
            $this->logError();
        }
        xml_parser_free($this->parser);
        return $this->errors;
    }

    private function logError() {
        $code = xml_get_error_code($this->parser);
        $this->errors[] = [
            'message' => xml_error_string($code),
            'line' => xml_get_current_line_number($this->parser),
            'column' => xml_get_current_column_number($this->parser),
            'byte_index' => xml_get_current_byte_index($this->parser)
        ];
    }
    // ... другие методы обработчиков
}

$xml = 'text';
$parser = new XmlParserWithDetailedErrors();
$errors = $parser->parse($xml);
print_r($errors);
?>
Array
(
    [0] => Array
        (
            [message] => mismatched tag
            [line] => 1
            [column] => 18
            [byte_index] => 17
        )

)

PHP xml_get_current_line_number function comments

En
Xml get current line number Get current line number for an XML parser