Олег Карнауховweb developerОбсудить проект

Блог

XML со стилями: почему карта сайта выглядела сломанной и при чём тут hreflang

Карта сайта открывалась в браузере одной плоской строкой. Причина — пространство имён XHTML внутри XML. Разбор, починка через XSL и ловушка с типом отдачи файла.

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

Причина: пространство имён XHTML

Разница была в одной строке объявлений. В моей карте есть hreflang-связки — теги, которые сообщают поисковику, что русская и английская версии страницы это одна страница на двух языках. Они живут в пространстве имён XHTML, и оно объявлено в корне документа.

Как только браузер видит объявленное пространство имён XHTML, он перестаёт считать файл «просто XML» и пытается отрисовать его как страницу. А для страницы теги loc, lastmod и priority — обычные строчные элементы без стилей, поэтому весь текст сливается в один абзац.

Проверил это экспериментом: взял ту же карту, убрал объявление и сами связки, открыл оба файла в одном браузере. Первый — плоская строка, второй — дерево.

sitemap.xmlxml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://example.com/</loc>
    <xhtml:link rel="alternate" hreflang="ru" href="https://example.com/"/>
    <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en"/>
    <lastmod>2026-08-13</lastmod>
  </url>
</urlset>
Вторая строка — инструкция на таблицу стилей. Роботы обязаны её игнорировать, браузер применит.

Починка: таблица стилей для XML

К карте прикладывается XSL — преобразование, которое превращает её в человекочитаемую таблицу. XSLT 1.0, потому что это всё, что когда-либо поддерживали браузеры. Стили внутри файла: он запрашивается отдельно, и никакого CSS сайта для него не существует.

Есть оговорка на будущее: в Chrome обсуждают отказ от XSLT. Если его уберут, карта вернётся к плоскому виду — то есть терять нечего, а для роботов не изменится ничего.

Ловушка: тип отдачи файла

После починки я открыл сам файл стилей — и получил страницу с заголовком сайта и пустой таблицей. Первая догадка была, что браузер применяет таблицу к самой себе, и я добавил в неё ветку «если карты нет, скажи, что ты таблица стилей».

Проверил — стало хуже: на странице появились оба блока сразу. Значит, браузер не выполняет преобразование, а просто печатает всю разметку, которую находит внутри файла, игнорируя xsl-элементы. Средствами XSLT это не лечится вовсе.

Лечится типом отдачи. Инструкция внутри карты называет text/xsl, и именно на неё браузер опирается, решая применить стили; сам файл должен всего лишь разбираться как XML. Поэтому отдаю его как application/xml: карта оформляется по-прежнему, а открытый напрямую файл показывается тем, чем является — исходником.

Тип отдачи .xslКарта оформляетсяСам файл открывается как
text/xslдасломанная страница
application/xmlдадерево исходника
не указаннетпоток байтов
Строка без типа — то, что получится, если забыть добавить расширение в список MIME-типов статического сервера.