{"id":20961,"date":"2026-10-01T18:14:10","date_gmt":"2026-10-01T16:14:10","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/"},"modified":"2026-10-01T18:29:19","modified_gmt":"2026-10-01T16:29:19","slug":"sitemap-checker-validator-schema-hreflang-image-video-news","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/","title":{"rendered":"Sitemap Checker &#038; Validator: Schema, hreflang, Image, Video and News Extensions"},"content":{"rendered":"<div class=\"lw-sv\" id=\"sv-wurzel\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<style>\n.lw-sv label.sv-feld { display: flex; flex-direction: column; gap: 6px; font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); margin-bottom: 12px; }\n.lw-sv textarea, .lw-sv input[type=url] { width: 100%; box-sizing: border-box; padding: 9px 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; font-size: 0.86rem; }\n.lw-sv textarea { min-height: 220px; resize: vertical; line-height: 1.45; }\n.lw-sv .sv-reihe { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 4px 0 6px; }\n.lw-sv button { padding: 9px 16px; border-radius: 6px; border: 1px solid var(--border, #2a2a35); background: var(--bg-body, #14141a); color: var(--text-primary, #e8e8ee); font-size: 0.92rem; cursor: pointer; }\n.lw-sv button.sv-haupt { background: var(--accent, #38bdf8); border-color: var(--accent, #38bdf8); color: var(--on-accent, #0a0e14); font-weight: 700; }\n.lw-sv button:focus-visible, .lw-sv input:focus-visible, .lw-sv textarea:focus-visible { outline: 2px solid var(--accent, #38bdf8); outline-offset: 2px; }\n.lw-sv .sv-datei { font-size: 0.86rem; color: var(--text-secondary, #a0a0b0); max-width: 100%; }\n.lw-sv .sv-status { min-height: 1.3em; margin: 10px 0 0; font-size: 0.92rem; color: var(--text-secondary, #a0a0b0); }\n.lw-sv .sv-status.sv-schlecht { color: var(--fail, #ff7b72); }\n.lw-sv .sv-h { font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.98rem; margin: 26px 0 8px; }\n.lw-sv .sv-tabelle { overflow-x: auto; }\n.lw-sv table { border-collapse: collapse; width: 100%; font-size: 0.88rem; }\n.lw-sv th, .lw-sv td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border, #2a2a35); vertical-align: top; color: var(--text-primary, #e8e8ee); }\n.lw-sv td:first-child { color: var(--text-secondary, #a0a0b0); white-space: nowrap; width: 38%; }\n.lw-sv td.sv-wert { font-family: monospace; word-break: break-all; }\n.lw-sv ul.sv-liste { list-style: none; margin: 0; padding: 0; }\n.lw-sv ul.sv-liste li { display: flex; gap: 10px; align-items: flex-start; padding: 9px 0; border-bottom: 1px solid var(--border, #2a2a35); font-size: 0.9rem; line-height: 1.5; color: var(--text-primary, #e8e8ee); }\n.lw-sv .sv-marke { flex: 0 0 auto; min-width: 74px; text-align: center; font-size: 0.74rem; font-weight: 700; padding: 2px 6px; border-radius: 4px; border: 1px solid currentColor; }\n.lw-sv .sv-fehler { color: var(--fail, #ff7b72); }\n.lw-sv .sv-warnung { color: var(--warn, #f0b429); }\n.lw-sv .sv-hinweis { color: var(--text-secondary, #a0a0b0); }\n.lw-sv .sv-gut { color: var(--pass, #3fb950); }\n.lw-sv .sv-zeilen { display: block; font-size: 0.8rem; color: var(--text-secondary, #a0a0b0); font-family: monospace; word-break: break-all; }\n.lw-sv .sv-klein { font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); line-height: 1.55; margin: 0 0 6px; }\n.lw-sv .sv-klein a { color: var(--accent, #38bdf8); }\n@media (max-width: 480px) {\n    .lw-sv { padding: 16px !important; }\n    .lw-sv td:first-child { white-space: normal; }\n    .lw-sv .sv-marke { min-width: 62px; }\n}\n<\/style>\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 18px;\">A sitemap can be checked before it is published, without being online anywhere. The validator reads pasted XML or a file (including .gz) in the browser and checks it against the sitemaps.org protocol and against Google&#039;s extensions for hreflang, images, videos and news. Every finding names its line. Nothing is uploaded.<\/p>\n<p>    <label class=\"sv-feld\">Sitemap XML (paste or select a file)<br \/>\n        <textarea id=\"sv-xml\" spellcheck=\"false\" autocomplete=\"off\" data-mp-mask placeholder=\"&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\"><\/textarea><br \/>\n    <\/label><\/p>\n<div class=\"sv-reihe\">\n        <input id=\"sv-datei\" class=\"sv-datei\" type=\"file\" accept=\".xml,.gz,.txt,application\/xml,text\/xml,application\/gzip\">\n    <\/div>\n<p>    <label class=\"sv-feld\" style=\"margin-top: 10px;\">Address of the file (optional, for the sitemaps.org location rule)<br \/>\n        <input id=\"sv-adresse\" type=\"url\" inputmode=\"url\" autocomplete=\"off\" data-mp-mask placeholder=\"https:\/\/example.com\/sitemap.xml\"><br \/>\n    <\/label><\/p>\n<div class=\"sv-reihe\">\n        <button type=\"button\" id=\"sv-los\" class=\"sv-haupt\">Check<\/button><br \/>\n        <button type=\"button\" id=\"sv-beispiel\">Example with errors<\/button><br \/>\n        <button type=\"button\" id=\"sv-leeren\">Clear<\/button>\n    <\/div>\n<p id=\"sv-status\" class=\"sv-status\" data-mp-mask aria-live=\"polite\">\n<div id=\"sv-ergebnis\" data-mp-mask hidden>\n<div class=\"sv-h\">Overview<\/div>\n<div class=\"sv-tabelle\">\n<table>\n<tbody id=\"sv-zahlen\" data-mp-mask><\/tbody>\n<\/table>\n<\/div>\n<div class=\"sv-h\">Findings<\/div>\n<ul id=\"sv-befunde\" class=\"sv-liste\" data-mp-mask><\/ul>\n<\/p><\/div>\n<div class=\"sv-h\">What is checked<\/div>\n<p class=\"sv-klein\">XML: well-formedness with line and column (unescaped &amp;, unclosed or wrongly nested tags, unknown entities, undeclared prefixes), UTF-8 encoding, at most 50,000 entries and 50 MB uncompressed.<\/p>\n<p class=\"sv-klein\">Protocol: root urlset or sitemapindex in the namespace http:\/\/www.sitemaps.org\/schemas\/sitemap\/0.9, exactly one loc per entry as an absolute, encoded address under 2,048 characters, lastmod in W3C format, changefreq and priority with permitted values, order as in the XSD, duplicates, mixed hosts.<\/p>\n<p class=\"sv-klein\">hreflang: rel=&quot;alternate&quot;, language code per ISO 639-1 with an optional region per ISO 3166-1 (Google does not accept es-419 or en-UK), self-reference in every group and return links between the entries of the file.<\/p>\n<p class=\"sv-klein\">Images, videos, news: image:loc, at most 1,000 images per address and the image tags removed in 2022; a video&#039;s required fields, duration 1 to 28,800 s, rating 0 to 5, yes\/no fields and deprecated tags; for news the publication, language, date, title, at most 1,000 entries and the two-day age limit.<\/p>\n<p class=\"sv-klein\">With the address of the file: the sitemaps.org location rule (only addresses below the file&#039;s folder, same scheme, same host). Google goes further when the sitemap is submitted in Search Console, so a violation is shown as a note. What the addresses answer live is not checked by the validator.<\/p>\n<div class=\"sv-h\">Related<\/div>\n<p class=\"sv-klein\">How twenty large sites split their sitemaps and which violations they contain is measured in the article \u201c<a href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/web-development\/sitemap-structures-24-sites-index-splitting-extensions-violations\/\">Sitemap Structures Measured at 24 Sites<\/a>\u201d.<\/p>\n<p class=\"sv-klein\">A published sitemap, with its index, child files and a sample of its addresses, is checked by the <a href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/xml-sitemap-auditor-lastmod-index-sample-check\/\">XML Sitemap Auditor<\/a>.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"A sitemap can be checked before it is published, without being online anywhere. The validator reads pasted XML or a file (including .gz) in the browser and checks it against the sitemaps.org protocol and against Google\\u0027s extensions for hreflang, images, videos and news. Every finding names its line. Nothing is uploaded.\",\"f_xml\":\"Sitemap XML (paste or select a file)\",\"f_adresse\":\"Address of the file (optional, for the sitemaps.org location rule)\",\"k_pruefen\":\"Check\",\"k_beispiel\":\"Example with errors\",\"k_leeren\":\"Clear\",\"h_ueberblick\":\"Overview\",\"h_befunde\":\"Findings\",\"h_regeln\":\"What is checked\",\"regel_1\":\"XML: well-formedness with line and column (unescaped \\u0026, unclosed or wrongly nested tags, unknown entities, undeclared prefixes), UTF-8 encoding, at most 50,000 entries and 50 MB uncompressed.\",\"regel_2\":\"Protocol: root urlset or sitemapindex in the namespace http:\\\/\\\/www.sitemaps.org\\\/schemas\\\/sitemap\\\/0.9, exactly one loc per entry as an absolute, encoded address under 2,048 characters, lastmod in W3C format, changefreq and priority with permitted values, order as in the XSD, duplicates, mixed hosts.\",\"regel_3\":\"hreflang: rel=\\u0022alternate\\u0022, language code per ISO 639-1 with an optional region per ISO 3166-1 (Google does not accept es-419 or en-UK), self-reference in every group and return links between the entries of the file.\",\"regel_4\":\"Images, videos, news: image:loc, at most 1,000 images per address and the image tags removed in 2022; a video\\u0027s required fields, duration 1 to 28,800 s, rating 0 to 5, yes\\\/no fields and deprecated tags; for news the publication, language, date, title, at most 1,000 entries and the two-day age limit.\",\"regel_5\":\"With the address of the file: the sitemaps.org location rule (only addresses below the file\\u0027s folder, same scheme, same host). Google goes further when the sitemap is submitted in Search Console, so a violation is shown as a note. What the addresses answer live is not checked by the validator.\",\"h_artikel\":\"Related\",\"art_vor\":\"How twenty large sites split their sitemaps and which violations they contain is measured in the article \u201c\",\"art_titel\":\"Sitemap Structures Measured at 24 Sites\",\"art_nach\":\"\u201d.\",\"auditor_vor\":\"A published sitemap, with its index, child files and a sample of its addresses, is checked by the \",\"auditor_href\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/xml-sitemap-auditor-lastmod-index-sample-check\\\/\",\"auditor_titel\":\"XML Sitemap Auditor\",\"auditor_nach\":\".\",\"s_leer\":\"No XML has been pasted.\",\"s_lese\":\"Reading the file \u2026\",\"s_pruefe\":\"Large file, check running \u2026\",\"s_zu_gross\":\"The file is larger than 60 MB and is not read. The limit is 50 MB.\",\"s_utf8\":\"The file is not valid UTF-8. The protocol requires UTF-8.\",\"s_lesefehler\":\"The file could not be read or decompressed.\",\"s_datei\":\"Read: {name}, {kb} KB.\",\"s_datei_gz\":\"Read and decompressed: {name}, {kb} KB uncompressed.\",\"s_beispiel\":\"Example loaded: four entries with seven built-in errors.\",\"z_art\":\"Type\",\"art_index\":\"Sitemap index (sitemapindex)\",\"art_urlset\":\"Sitemap (urlset)\",\"z_sitemaps\":\"Child sitemaps\",\"z_eintraege\":\"Entries\",\"z_groesse\":\"Size\",\"groesse_wert\":\"{kb} KB, {anteil} % of the 50 MB limit\",\"z_hosts\":\"Hosts\",\"z_lastmod\":\"lastmod\",\"lastmod_wert\":\"{mit} of {n} with a valid date, {verschieden} distinct values\",\"z_erweiterungen\":\"Extensions\",\"erw_wert\":\"{hreflang} hreflang links, {bilder} images, {videos} videos, {news} news\",\"z_urteil\":\"Result\",\"urteil_fehler\":\"{fehler} errors, {warnung} warnings, {hinweis} notes\",\"urteil_warnung\":\"no errors, {warnung} warnings, {hinweis} notes\",\"urteil_gut\":\"no errors and no warnings, {hinweis} notes\",\"stufe_fehler\":\"Error\",\"stufe_warnung\":\"Warning\",\"stufe_hinweis\":\"Note\",\"stufe_gut\":\"OK\",\"zeilen_eine\":\"Line {liste}\",\"zeilen_mehr\":\"{n} times, lines {liste}\",\"anzahl\":\"{n} times\",\"dezimal\":\".\",\"tausender\":\",\",\"b_leer\":\"The input is empty.\",\"b_xml_kaputt\":\"Not well-formed XML: {grund} (line {zeile}, column {spalte}). An XML parser stops here, and crawlers discard the file.\",\"xml_ampersand\":\"an \\u0026 without an entity; in addresses it has to be written as \\u0026amp;\",\"xml_zeichenref\":\"the character reference {wert} does not stand for a character allowed in XML\",\"xml_entitaet\":\"the entity \\u0026{name}; is not defined in XML; only \\u0026amp; \\u0026lt; \\u0026gt; \\u0026quot; \\u0026apos; and numeric references are allowed\",\"xml_zeichen\":\"a control character forbidden in XML ({wert})\",\"xml_text_aussen\":\"text outside the root element\",\"xml_pi_offen\":\"a processing instruction \\u003C? without ?\\u003E\",\"xml_decl_pos\":\"the XML declaration \\u003C?xml \u2026?\\u003E is not at the very start of the file; even one empty line before it is an error\",\"xml_kommentar_offen\":\"a comment \\u003C!-- without --\\u003E\",\"xml_cdata_offen\":\"a CDATA section without ]]\\u003E\",\"xml_doctype_pos\":\"a DOCTYPE declaration after the root element\",\"xml_doctype_offen\":\"a DOCTYPE declaration without an end\",\"xml_name\":\"a \\u003C without a valid tag name; a \\u003C in text has to be written as \\u0026lt;\",\"xml_tag_offen\":\"the tag \\u003C{name}\\u003E is not closed\",\"xml_schliessend_ohne\":\"\\u003C\\\/{name}\\u003E closes an element that was never opened\",\"xml_tag_falsch\":\"\\u003C\\\/{gefunden}\\u003E closes \\u003C{erwartet}\\u003E from line {zeile_offen}\",\"xml_zweite_wurzel\":\"a second root element; a file may have only one\",\"xml_attribut\":\"a malformed attribute in \\u003C{name}\\u003E\",\"xml_attr_quote\":\"the value of {name} is not in quotation marks\",\"xml_lt_attr\":\"a \\u003C character in the value of {name}\",\"xml_attr_doppelt\":\"the attribute {name} appears twice in the same tag\",\"xml_prefix_unbekannt\":\"the prefix {prefix} in \\u003C{name}\\u003E is not declared; xmlns:{prefix}=\\u0022\u2026\\u0022 is missing on the root element\",\"xml_tag_offen_ende\":\"\\u003C{name}\\u003E is not closed before the end of the file; the file is probably truncated\",\"xml_keine_wurzel\":\"the file contains no element\",\"b_encoding\":\"The XML declaration names the encoding {wert}. The protocol requires UTF-8.\",\"b_doctype\":\"The file carries a DOCTYPE declaration. A sitemap needs none; no crawler knows entities defined in it.\",\"b_zu_gross\":\"The file is {mb} MB. The limit is 50 MB uncompressed; the rest is not read.\",\"b_wurzel_falsch\":\"The root element is \\u003C{name}\\u003E. A sitemap starts with \\u003Curlset\\u003E, an index with \\u003Csitemapindex\\u003E; an HTML page in this place is usually an error page.\",\"b_wurzel_prefix\":\"The root element carries a prefix ({name}). That is allowed if the namespace is right, but unusual.\",\"b_ns_falsch\":\"The namespace is {ns} instead of http:\\\/\\\/www.sitemaps.org\\\/schemas\\\/sitemap\\\/0.9. Namespaces are compared character by character; https:\\\/\\\/ or Google\\u0027s old version 0.84 is a different one.\",\"b_ns_fehlt\":\"xmlns=\\u0022http:\\\/\\\/www.sitemaps.org\\\/schemas\\\/sitemap\\\/0.9\\u0022 is missing on the root element.\",\"b_datei_adresse\":\"The address of the file ({wert}) is not an http or https address; the location rule was not checked.\",\"b_element_unbekannt\":\"\\u003C{name}\\u003E is not allowed in \\u003C{in}\\u003E. An index contains only \\u003Csitemap\\u003E, a sitemap only \\u003Curl\\u003E, and changefreq and priority exist only in \\u003Curl\\u003E.\",\"b_leer_liste\":\"The file contains not a single entry.\",\"b_zu_viele\":\"{n} entries. The limit is 50,000 per file; more belong in several files and an index.\",\"b_element_doppelt\":\"\\u003C{name}\\u003E appears more than once in one entry.\",\"b_reihenfolge\":\"The child elements are not in the order of the XSD (loc, lastmod, changefreq, priority, then extensions). Google does not mind; a strict schema check does.\",\"b_loc_fehlt\":\"An entry has no \\u003Cloc\\u003E or an empty one.\",\"b_loc_leerraum\":\"There are spaces or line breaks around the address in \\u003Cloc\\u003E.\",\"b_loc_relativ\":\"Relative address {wert}. Full addresses with scheme and host are required.\",\"b_loc_schema\":\"Address without http or https: {wert}.\",\"b_loc_lang\":\"The address has 2,048 characters or more: {wert} \u2026\",\"b_loc_unkodiert\":\"Unencoded characters in the address (spaces, umlauts, quotation marks): {wert}. Percent-encoding is required.\",\"b_loc_fragment\":\"The address contains a fragment (#): {wert}. Crawlers cut it off, and the entry then duplicates another.\",\"b_ort_fremdhost\":\"Address on a different host from the file ({host}): {wert}. This only works if that host\\u0027s robots.txt points to the sitemap.\",\"b_index_fremdhost\":\"The index names a sitemap on a host other than {host}: {wert}.\",\"b_ort_ausserhalb\":\"Address outside {ordner}: {wert}. Under sitemaps.org a sitemap applies only to its folder and below; Google still uses it if it is submitted in Search Console.\",\"b_index_ausserhalb\":\"Child sitemap outside {ordner}: {wert}. Google requires child sitemaps in the index\\u0027s folder or below.\",\"b_doppelt\":\"Duplicate entry: {wert}.\",\"b_lastmod_format\":\"lastmod \u201c{wert}\u201d is not a W3C date. Valid examples are 2026-10-01 or 2026-10-01T14:05:00+02:00.\",\"b_lastmod_ohne_zone\":\"lastmod \u201c{wert}\u201d has a time without a time zone. The XSD accepts it; the W3C format requires Z or an offset such as +02:00.\",\"b_lastmod_zukunft\":\"lastmod \u201c{wert}\u201d is in the future.\",\"b_changefreq_wert\":\"changefreq \u201c{wert}\u201d is not a permitted value (always, hourly, daily, weekly, monthly, yearly, never).\",\"b_priority_wert\":\"priority \u201c{wert}\u201d is not between 0.0 and 1.0.\",\"b_hreflang_rel\":\"xhtml:link with rel=\\u0022{wert}\\u0022 instead of rel=\\u0022alternate\\u0022.\",\"b_hreflang_code\":\"hreflang \u201c{wert}\u201d is not a valid code. The language per ISO 639-1 comes first, then optionally the region per ISO 3166-1, such as de or de-AT; Google does not accept es-419, en-UK or a region on its own.\",\"b_hreflang_href\":\"xhtml:link without a full address in href: {wert}.\",\"b_ext_platz\":\"\\u003C{name}\\u003E sits directly in \\u003Curl\\u003E. It belongs in its parent element (image:image, video:video or news:news).\",\"b_bild_loc_fehlt\":\"image:image without image:loc.\",\"b_bild_url\":\"image:loc is not a full address: {wert}.\",\"b_bild_veraltet\":\"Google removed \\u003C{name}\\u003E from image sitemaps in 2022; the value is no longer read.\",\"b_ns_variante\":\"\\u003C{name}\\u003E is in the namespace {ns}. The http version is expected, such as http:\\\/\\\/www.google.com\\\/schemas\\\/sitemap-image\\\/1.1 or http:\\\/\\\/www.w3.org\\\/1999\\\/xhtml; a different spelling is a different namespace.\",\"b_bild_zu_viele\":\"{n} images on one address. Google takes at most 1,000 per url.\",\"b_hreflang_doppelt\":\"hreflang \u201c{wert}\u201d appears twice in one entry with different addresses.\",\"b_hreflang_selbst\":\"The hreflang group of {wert} does not name the page itself. Google requires every version to include itself in its list.\",\"b_hreflang_rueck\":\"{von} points to {nach}, but {nach} does not point back. Without a return link Google may discard the annotation.\",\"b_hreflang_extern\":\"{n} hreflang targets are not in this file; their return links cannot be checked here.\",\"b_hreflang_ok\":\"hreflang in {n} entries: codes valid, self-references and return links within the file complete.\",\"b_news_zu_viele\":\"{n} news entries. Google takes at most 1,000 per news sitemap.\",\"b_host_gemischt\":\"Addresses on {n} hosts: {liste}. A sitemap is meant to contain addresses of one host.\",\"b_schema_gemischt\":\"http and https mixed: {http} with http, {https} with https.\",\"b_lastmod_fehlt\":\"No entry has a lastmod. The field is optional, but it is the only one of the core format that Google uses.\",\"b_lastmod_teil\":\"{mit} of {n} entries have a lastmod.\",\"b_lastmod_gleich\":\"All {n} entries carry the same lastmod ({wert}). Such a date describes the generator run, not the pages, and Google relies only on a lastmod that is verifiably accurate.\",\"b_prio_cf\":\"priority appears in {priority}, changefreq in {changefreq} entries. Google ignores both fields.\",\"b_fremd_ns\":\"Elements from further namespaces: {liste}. They were counted but not checked.\",\"b_sauber\":\"No errors and no warnings in {n} entries.\",\"b_video_pflicht\":\"Video without a required field: {liste}.\",\"b_video_beschreibung\":\"video:description has {n} characters; the limit is 2,048.\",\"b_video_dauer\":\"video:duration \u201c{wert}\u201d is not a whole number from 1 to 28800 seconds.\",\"b_video_rating\":\"video:rating \u201c{wert}\u201d is not between 0.0 and 5.0.\",\"b_video_datum\":\"{name} \u201c{wert}\u201d is not a W3C date with a time zone.\",\"b_video_janein\":\"{name} \u201c{wert}\u201d: only yes and no in lower case are allowed.\",\"b_video_relationship\":\"{name} without relationship=\\u0022allow\\u0022 or \\u0022deny\\u0022.\",\"b_video_platform\":\"video:platform \u201c{wert}\u201d: only web, mobile and tv are allowed, separated by spaces.\",\"b_video_tags\":\"{n} video:tag elements in one video; Google takes at most 32.\",\"b_video_uploader\":\"video:uploader has {n} characters; the limit is 255.\",\"b_video_veraltet\":\"{name} is deprecated and no longer read.\",\"b_news_sprache\":\"news:language \u201c{wert}\u201d: an ISO 639 code of two or three letters is required, the only exceptions being zh-cn and zh-tw.\",\"b_news_datum\":\"news:publication_date \u201c{wert}\u201d is not a W3C date.\",\"b_news_alt\":\"news:publication_date {wert} is more than two days ago. A news sitemap is meant to list only articles from the last two days.\",\"b_news_pflicht\":\"news:news without a required field: {liste}.\"};<\/p>\n<p>    \/\/ KERN-ANFANG\n    var NS_SM = 'http:\/\/www.sitemaps.org\/schemas\/sitemap\/0.9';\n    var NS_IMG = 'http:\/\/www.google.com\/schemas\/sitemap-image\/1.1';\n    var NS_VID = 'http:\/\/www.google.com\/schemas\/sitemap-video\/1.1';\n    var NS_NEWS = 'http:\/\/www.google.com\/schemas\/sitemap-news\/0.9';\n    var NS_XHTML = 'http:\/\/www.w3.org\/1999\/xhtml';\n    var MAX_EINTRAEGE = 50000, MAX_BYTES = 52428800, MAX_URL = 2048;\n    var STUFEN = ['fehler', 'warnung', 'hinweis', 'gut'];\n    var CHANGEFREQ = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];<\/p>\n<p>    function utf8Laenge(s) {\n        var n = 0;\n        for (var i = 0; i < s.length; i++) {\n            var c = s.charCodeAt(i);\n            if (c < 0x80) { n += 1; } else if (c < 0x800) { n += 2; } else if (c >= 0xD800 && c <= 0xDBFF) { n += 4; i++; } else { n += 3; }\n        }\n        return n;\n    }\n\n    \/\/ Zeilenanfaenge einmal sammeln, Position per Halbierung\n    function zeilenIndex(s) {\n        var a = [0], i = -1;\n        while ((i = s.indexOf('\\n', i + 1)) !== -1) { a.push(i + 1); }\n        return a;\n    }\n    function position(index, off) {\n        var lo = 0, hi = index.length - 1;\n        while (lo < hi) { var m = (lo + hi + 1) >> 1; if (index[m] <= off) { lo = m; } else { hi = m - 1; } }\n        return { zeile: lo + 1, spalte: off - index[lo] + 1 };\n    }\n\n    \/\/ --- XML lesen: nicht validierend, aber streng bei Wohlgeformtheit ---------\n    var NAME_RE = \/[A-Za-z_\\u00C0-\\uFFFF][A-Za-z0-9_.\\-:\\u00B7\\u00C0-\\uFFFF]*\/y;\n    var ENT_RE = \/&#038;(#x[0-9a-fA-F]+|#[0-9]+|[A-Za-z_][A-Za-z0-9_.\\-]*)?(;)?\/g;\n    var VORDEF = { amp: '&#038;', lt: '<', gt: '>', quot: '\"', apos: \"'\" };<\/p>\n<p>    function xmlLesen(s) {\n        var i = 0, n = s.length, stapel = [], wurzel = null, decl = null, bom = false, doctype = false;\n        function halt(code, off, daten) { var e = new Error(code); e.xml = { code: code, off: off, daten: daten || {} }; throw e; }\n        function name(at) { NAME_RE.lastIndex = at; var m = NAME_RE.exec(s); return m ? m[0] : null; }\n        function entitaeten(str, basis) {\n            if (str.indexOf('&') === -1) { return str; }\n            ENT_RE.lastIndex = 0;\n            return str.replace(ENT_RE, function (alles, nm, semi, off) {\n                if (!nm || !semi) { halt('ampersand', basis + off); }\n                if (nm.charAt(0) === '#') {\n                    var cp = nm.charAt(1) === 'x' ? parseInt(nm.slice(2), 16) : parseInt(nm.slice(1), 10);\n                    if (!(cp === 9 || cp === 10 || cp === 13 || (cp >= 32 && cp <= 0xD7FF) || (cp >= 0xE000 && cp <= 0xFFFD) || (cp >= 0x10000 && cp <= 0x10FFFF))) { halt('zeichenref', basis + off, { wert: alles }); }\n                    return String.fromCodePoint(cp);\n                }\n                if (!Object.prototype.hasOwnProperty.call(VORDEF, nm)) { halt('entitaet', basis + off, { name: nm }); }\n                return VORDEF[nm];\n            });\n        }\n        try {\n            var steuer = \/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\uFFFE\\uFFFF]\/.exec(s);\n            if (steuer) { halt('zeichen', steuer.index, { wert: 'U+' + ('000' + steuer[0].charCodeAt(0).toString(16).toUpperCase()).slice(-4) }); }\n            if (s.charCodeAt(0) === 0xFEFF) { bom = true; i = 1; }\n            while (i < n) {\n                var lt = s.indexOf('<', i), ende = lt === -1 ? n : lt;\n                if (ende > i) {\n                    var stueck = s.slice(i, ende), oben = stapel[stapel.length - 1];\n                    if (!oben) { var nw = stueck.search(\/\\S\/); if (nw !== -1) { halt('text_aussen', i + nw); } }\n                    else if (\/\\S\/.test(stueck) || !oben.kinder.length) { oben.text += entitaeten(stueck, i); }\n                    i = ende;\n                    if (lt === -1) { break; }\n                }\n                if (s.startsWith('<?', i)) {\n                    var e1 = s.indexOf('?>', i + 2);\n                    if (e1 === -1) { halt('pi_offen', i); }\n                    var pi = s.slice(i + 2, e1);\n                    if (\/^xml(\\s|$)\/i.test(pi)) { if (i !== (bom ? 1 : 0)) { halt('decl_pos', i); } decl = pi; }\n                    i = e1 + 2; continue;\n                }\n                if (s.startsWith('<!--', i)) { var e2 = s.indexOf('-->', i + 4); if (e2 === -1) { halt('kommentar_offen', i); } i = e2 + 3; continue; }\n                if (s.startsWith('<![CDATA[', i)) {\n                    if (!stapel.length) { halt('text_aussen', i); }\n                    var e3 = s.indexOf(']]>', i + 9); if (e3 === -1) { halt('cdata_offen', i); }\n                    stapel[stapel.length - 1].text += s.slice(i + 9, e3); i = e3 + 3; continue;\n                }\n                if (s.startsWith('<!DOCTYPE', i)) {\n                    if (wurzel) { halt('doctype_pos', i); }\n                    doctype = true;\n                    var tiefe = 0, j0 = i + 9;\n                    for (; j0 < n; j0++) { var ch = s.charAt(j0); if (ch === '[') { tiefe++; } else if (ch === ']') { tiefe--; } else if (ch === '>' && tiefe <= 0) { break; } }\n                    if (j0 >= n) { halt('doctype_offen', i); }\n                    i = j0 + 1; continue;\n                }\n                if (s.charAt(i + 1) === '\/') {\n                    var zn = name(i + 2);\n                    if (!zn) { halt('name', i); }\n                    var j1 = i + 2 + zn.length;\n                    while (\/\\s\/.test(s.charAt(j1))) { j1++; }\n                    if (s.charAt(j1) !== '>') { halt('tag_offen', i, { name: zn }); }\n                    var offen = stapel.pop();\n                    if (!offen) { halt('schliessend_ohne', i, { name: zn }); }\n                    if (offen.name !== zn) { halt('tag_falsch', i, { gefunden: zn, erwartet: offen.name, off_offen: offen.off }); }\n                    i = j1 + 1; continue;\n                }\n                if (wurzel && !stapel.length) { halt('zweite_wurzel', i); }\n                var tn = name(i + 1);\n                if (!tn) { halt('name', i); }\n                var j = i + 1 + tn.length, attrs = {}, selbst = false;\n                for (;;) {\n                    var vor = j;\n                    while (\/\\s\/.test(s.charAt(j))) { j++; }\n                    var c = s.charAt(j);\n                    if (c === '>') { j++; break; }\n                    if (c === '\/' && s.charAt(j + 1) === '>') { selbst = true; j += 2; break; }\n                    if (j >= n) { halt('tag_offen', i, { name: tn }); }\n                    var an = name(j);\n                    if (!an || j === vor) { halt('attribut', j, { name: tn }); }\n                    j += an.length;\n                    while (\/\\s\/.test(s.charAt(j))) { j++; }\n                    if (s.charAt(j) !== '=') { halt('attribut', j, { name: tn }); }\n                    j++;\n                    while (\/\\s\/.test(s.charAt(j))) { j++; }\n                    var q = s.charAt(j);\n                    if (q !== '\"' && q !== \"'\") { halt('attr_quote', j, { name: an }); }\n                    var ae = s.indexOf(q, j + 1);\n                    if (ae === -1) { halt('tag_offen', i, { name: tn }); }\n                    var roh = s.slice(j + 1, ae);\n                    var ltA = roh.indexOf('<');\n                    if (ltA !== -1) { halt('lt_attr', j + 1 + ltA, { name: an }); }\n                    if (Object.prototype.hasOwnProperty.call(attrs, an)) { halt('attr_doppelt', j, { name: an }); }\n                    attrs[an] = entitaeten(roh, j + 1);\n                    j = ae + 1;\n                }\n                var eltern = stapel[stapel.length - 1] || null;\n                var nsmap = eltern ? eltern.nsmap : { xml: 'http:\/\/www.w3.org\/XML\/1998\/namespace' };\n                for (var a in attrs) {\n                    if (a === 'xmlns' || a.indexOf('xmlns:') === 0) {\n                        if (nsmap === (eltern &#038;&#038; eltern.nsmap)) { nsmap = Object.assign({}, nsmap); }\n                        nsmap[a === 'xmlns' ? '' : a.slice(6)] = attrs[a];\n                    }\n                }\n                var dp = tn.indexOf(':'), prefix = dp === -1 ? '' : tn.slice(0, dp), lokal = dp === -1 ? tn : tn.slice(dp + 1);\n                if (prefix &#038;&#038; nsmap[prefix] === undefined) { halt('prefix_unbekannt', i, { prefix: prefix, name: tn }); }\n                var knoten = { name: tn, prefix: prefix, lokal: lokal, ns: nsmap[prefix] || '', attrs: attrs, kinder: [], text: '', off: i, nsmap: nsmap };\n                if (eltern) { eltern.kinder.push(knoten); } else { wurzel = knoten; }\n                if (!selbst) { stapel.push(knoten); }\n                i = j;\n            }\n            if (stapel.length) { var o = stapel[stapel.length - 1]; halt('tag_offen_ende', o.off, { name: o.name }); }\n            if (!wurzel) { halt('keine_wurzel', 0); }\n        } catch (e) {\n            if (!e.xml) { throw e; }\n            return { wurzel: null, fehler: e.xml, decl: decl, bom: bom, doctype: doctype };\n        }\n        return { wurzel: wurzel, fehler: null, decl: decl, bom: bom, doctype: doctype };\n    }\n\n    \/\/ --- Feldpruefungen --------------------------------------------------------\n    var W3C_RE = \/^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})?)?$\/;\n    \/\/ 'ok', 'ohne_zone' (Uhrzeit ohne Zeitzone: XSD nimmt es, W3C Datetime nicht) oder 'falsch'\n    function datumArt(w) {\n        var m = W3C_RE.exec(w);\n        if (!m) { return 'falsch'; }\n        var jahr = +m[1], mon = +m[2], tag = +m[3];\n        if (mon < 1 || mon > 12 || tag < 1 || tag > new Date(Date.UTC(jahr, mon, 0)).getUTCDate()) { return 'falsch'; }\n        if (m[4] !== undefined) {\n            if (+m[4] > 23 || +m[5] > 59 || (m[6] !== undefined && +m[6] > 59)) { return 'falsch'; }\n            if (m[7] && m[7] !== 'Z') { var zh = +m[7].slice(1, 3), zm = +m[7].slice(4, 6); if (zh > 14 || zm > 59) { return 'falsch'; } }\n            if (m[7] === undefined) { return m[6] === undefined ? 'falsch' : 'ohne_zone'; }\n        }\n        return 'ok';\n    }\n    function datumMs(w) {\n        var m = W3C_RE.exec(w);\n        if (!m) { return NaN; }\n        var t = Date.UTC(+m[1], +m[2] - 1, +m[3], m[4] ? +m[4] : 0, m[5] ? +m[5] : 0, m[6] ? +m[6] : 0);\n        if (m[7] && m[7] !== 'Z') { var vz = m[7].charAt(0) === '-' ? -1 : 1; t -= vz * (+m[7].slice(1, 3) * 60 + +m[7].slice(4, 6)) * 60000; }\n        return t;\n    }\n    \/\/ Probleme einer Adresse; leer heisst sauber\n    function urlProbleme(u) {\n        var p = [];\n        if (!\/^[A-Za-z][A-Za-z0-9+.\\-]*:\/.test(u)) { p.push('relativ'); return p; }\n        if (!\/^https?:\\\/\\\/[^\\\/?#\\s]+\/i.test(u)) { p.push('schema'); return p; }\n        if (u.length >= MAX_URL) { p.push('lang'); }\n        if (\/[\\s\"<>{}|\\\\^`]|[^\\x00-\\x7F]\/.test(u)) { p.push('unkodiert'); }\n        if (u.indexOf('#') !== -1) { p.push('fragment'); }\n        return p;\n    }\n    function urlTeile(u) {\n        var m = \/^(https?):\\\/\\\/([^\\\/?#]+)([^?#]*)\/i.exec(u);\n        if (!m) { return null; }\n        var host = m[2].toLowerCase().replace(\/:(80|443)$\/, '');\n        return { schema: m[1].toLowerCase(), host: host, pfad: m[3] || '\/' };\n    }\n    function unterhalb(u, basis) {\n        var t = urlTeile(u);\n        if (!t || !basis) { return true; }\n        return t.schema === basis.schema && t.host === basis.host && t.pfad.indexOf(basis.ordner) === 0;\n    }\n    var HREFLANG_RE = \/^([a-z]{2})(-[a-z]{4})?(-([a-z]{2}))?$\/i;\n    function hreflangGueltig(c) {\n        if (\/^x-default$\/i.test(c)) { return true; }\n        var m = HREFLANG_RE.exec(c);\n        if (!m) { return false; }\n        if (m[4] && \/^(uk|eu)$\/i.test(m[4])) { return false; }\n        return true;\n    }\n    function kind(knoten, ns, lokal) {\n        for (var i = 0; i < knoten.kinder.length; i++) { var k = knoten.kinder[i]; if (k.ns === ns &#038;&#038; k.lokal === lokal) { return k; } }\n        return null;\n    }\n    function kinderVon(knoten, ns, lokal) {\n        return knoten.kinder.filter(function (k) { return k.ns === ns &#038;&#038; k.lokal === lokal; });\n    }\n    function textVon(k) { return k ? k.text.trim() : ''; }\n\n    \/\/ --- Pruefung --------------------------------------------------------------\n    function pruefen(s, opt) {\n        opt = opt || {};\n        var jetzt = typeof opt.jetzt === 'number' ? opt.jetzt : Date.now();\n        var sammel = {}, reihe = [];\n        function b(key, stufe, off, daten) {\n            var f = sammel[key];\n            if (!f) { f = sammel[key] = { key: key, stufe: stufe, n: 0, stellen: [], daten: daten || {} }; reihe.push(f); }\n            f.n++;\n            if (typeof off === 'number' &#038;&#038; f.stellen.length < 5) { f.stellen.push(off); }\n            return f;\n        }\n        var zahlen = { art: null, eintraege: 0, bytes: utf8Laenge(s), hosts: {}, mitLastmod: 0, lastmodVerschieden: 0, bilder: 0, videos: 0, news: 0, hreflang: 0, fremdNs: {} };\n        var index = null;\n        function ergebnis() {\n            reihe.sort(function (a, c) { return STUFEN.indexOf(a.stufe) - STUFEN.indexOf(c.stufe); });\n            var zaehl = { fehler: 0, warnung: 0, hinweis: 0, gut: 0 };\n            reihe.forEach(function (f) { zaehl[f.stufe]++; });\n            if (!index) { index = zeilenIndex(s); }\n            reihe.forEach(function (f) { f.zeilen = f.stellen.map(function (o) { return position(index, o).zeile; }); });\n            return { befunde: reihe, stufen: zaehl, zahlen: zahlen, urteil: zaehl.fehler ? 'fehler' : (zaehl.warnung ? 'warnung' : 'gut') };\n        }\n\n        if (!\/\\S\/.test(s)) { b('leer', 'fehler'); return ergebnis(); }\n        var x = xmlLesen(s);\n        if (x.fehler) {\n            index = zeilenIndex(s);\n            var pos = position(index, x.fehler.off), d = Object.assign({ code: x.fehler.code, zeile: pos.zeile, spalte: pos.spalte }, x.fehler.daten);\n            if (d.off_offen !== undefined) { d.zeile_offen = position(index, d.off_offen).zeile; delete d.off_offen; }\n            b('xml_kaputt', 'fehler', x.fehler.off, d);\n            return ergebnis();\n        }\n        if (x.decl) {\n            var enc = \/encoding\\s*=\\s*[\"']([^\"']+)[\"']\/i.exec(x.decl);\n            if (enc &#038;&#038; !\/^utf-?8$\/i.test(enc[1])) { b('encoding', 'fehler', 0, { wert: enc[1] }); }\n        }\n        if (x.doctype) { b('doctype', 'hinweis', 0); }\n        if (zahlen.bytes > MAX_BYTES) { b('zu_gross', 'fehler', null, { mb: (zahlen.bytes \/ 1048576).toFixed(1) }); }<\/p>\n<p>        var w = x.wurzel;\n        if (w.lokal !== 'urlset' && w.lokal !== 'sitemapindex') { b('wurzel_falsch', 'fehler', w.off, { name: w.name }); return ergebnis(); }\n        var istIndex = w.lokal === 'sitemapindex';\n        zahlen.art = istIndex ? 'index' : 'urlset';\n        if (w.prefix) { b('wurzel_prefix', 'hinweis', w.off, { name: w.name }); }\n        if (w.ns !== NS_SM) { b(w.ns ? 'ns_falsch' : 'ns_fehlt', 'fehler', w.off, { ns: w.ns }); }\n        var smNs = w.ns;<\/p>\n<p>        var basis = null;\n        if (opt.datei) {\n            var dt = urlTeile(String(opt.datei).trim());\n            if (dt) { basis = { schema: dt.schema, host: dt.host, ordner: dt.pfad.replace(\/[^\\\/]*$\/, '') }; }\n            else { b('datei_adresse', 'warnung', null, { wert: opt.datei }); }\n        }<\/p>\n<p>        var eintragName = istIndex ? 'sitemap' : 'url';\n        var eintraege = [];\n        w.kinder.forEach(function (k) {\n            if (k.ns === smNs && k.lokal === eintragName) { eintraege.push(k); }\n            else if (k.ns === smNs) { b('element_unbekannt', 'fehler', k.off, { name: k.name, in: w.name }); }\n            else { zahlen.fremdNs[k.ns || '-'] = (zahlen.fremdNs[k.ns || '-'] || 0) + 1; }\n        });\n        zahlen.eintraege = eintraege.length;\n        if (!eintraege.length) { b('leer_liste', 'warnung', w.off); }\n        if (eintraege.length > MAX_EINTRAEGE) { b('zu_viele', 'fehler', null, { n: eintraege.length }); }<\/p>\n<p>        var ORDNUNG = istIndex ? { loc: 0, lastmod: 1 } : { loc: 0, lastmod: 1, changefreq: 2, priority: 3 };\n        var gesehen = {}, schemas = {}, lastmodWerte = {}, prio = 0, cf = 0;\n        var hrefs = {}, hreflangListen = [];<\/p>\n<p>        eintraege.forEach(function (e) {\n            var stufeVor = -1, reihenfolgeGemeldet = false, zaehlKern = {};\n            e.kinder.forEach(function (k) {\n                var rang;\n                if (k.ns === smNs) {\n                    if (!Object.prototype.hasOwnProperty.call(ORDNUNG, k.lokal)) { b('element_unbekannt', 'fehler', k.off, { name: k.name, in: e.name }); return; }\n                    zaehlKern[k.lokal] = (zaehlKern[k.lokal] || 0) + 1;\n                    if (zaehlKern[k.lokal] === 2) { b('element_doppelt', 'fehler', k.off, { name: k.name }); }\n                    rang = ORDNUNG[k.lokal];\n                } else { rang = 9; }\n                if (rang < stufeVor &#038;&#038; !reihenfolgeGemeldet) { b('reihenfolge', 'hinweis', k.off); reihenfolgeGemeldet = true; }\n                stufeVor = Math.max(stufeVor, rang);\n            });\n\n            var locK = kind(e, smNs, 'loc');\n            var loc = textVon(locK);\n            if (!locK || !loc) { b('loc_fehlt', 'fehler', e.off); }\n            else {\n                if (locK.text !== loc) { b('loc_leerraum', 'hinweis', locK.off); }\n                urlProbleme(loc).forEach(function (p) { b('loc_' + p, p === 'fragment' || p === 'unkodiert' ? 'warnung' : 'fehler', locK.off, { wert: loc.slice(0, 120) }); });\n                var t = urlTeile(loc);\n                if (t) {\n                    zahlen.hosts[t.host] = (zahlen.hosts[t.host] || 0) + 1;\n                    schemas[t.schema] = (schemas[t.schema] || 0) + 1;\n                    if (basis &#038;&#038; t.host !== basis.host) { b(istIndex ? 'index_fremdhost' : 'ort_fremdhost', 'warnung', locK.off, { wert: loc.slice(0, 120), host: basis.host }); }\n                    else if (basis &#038;&#038; !unterhalb(loc, basis)) { b(istIndex ? 'index_ausserhalb' : 'ort_ausserhalb', 'hinweis', locK.off, { wert: loc.slice(0, 120), ordner: basis.schema + ':\/\/' + basis.host + basis.ordner }); }\n                }\n                if (gesehen[loc]) { b('doppelt', 'warnung', locK.off, { wert: loc.slice(0, 120) }); } else { gesehen[loc] = true; }\n            }\n\n            var lm = kind(e, smNs, 'lastmod');\n            if (lm) {\n                var lmw = textVon(lm), art = datumArt(lmw);\n                if (art === 'falsch') { b('lastmod_format', 'fehler', lm.off, { wert: lmw.slice(0, 40) }); }\n                else {\n                    zahlen.mitLastmod++;\n                    lastmodWerte[lmw] = true;\n                    if (art === 'ohne_zone') { b('lastmod_ohne_zone', 'warnung', lm.off, { wert: lmw }); }\n                    if (datumMs(lmw) > jetzt + 86400000) { b('lastmod_zukunft', 'warnung', lm.off, { wert: lmw }); }\n                }\n            }\n            if (istIndex) { return; }<\/p>\n<p>            var cfK = kind(e, smNs, 'changefreq');\n            if (cfK) { cf++; if (CHANGEFREQ.indexOf(textVon(cfK)) === -1) { b('changefreq_wert', 'fehler', cfK.off, { wert: textVon(cfK).slice(0, 30) }); } }\n            var prK = kind(e, smNs, 'priority');\n            if (prK) {\n                prio++;\n                var pw = textVon(prK);\n                if (!\/^\\+?(\\d+(\\.\\d*)?|\\.\\d+)$\/.test(pw) || parseFloat(pw) > 1) { b('priority_wert', 'fehler', prK.off, { wert: pw.slice(0, 30) }); }\n            }<\/p>\n<p>            \/\/ Erweiterungen\n            var bilderHier = 0, sprachen = [];\n            e.kinder.forEach(function (k) {\n                if (k.ns === smNs) { return; }\n                if (k.ns === NS_XHTML && k.lokal === 'link') {\n                    zahlen.hreflang++;\n                    var rel = k.attrs.rel, hl = k.attrs.hreflang, href = (k.attrs.href || '').trim();\n                    if (rel !== 'alternate') { b('hreflang_rel', 'fehler', k.off, { wert: rel === undefined ? '-' : rel }); return; }\n                    if (!hl || !hreflangGueltig(hl)) { b('hreflang_code', 'fehler', k.off, { wert: hl === undefined ? '-' : hl }); }\n                    if (!href || urlProbleme(href).some(function (p) { return p === 'relativ' || p === 'schema'; })) { b('hreflang_href', 'fehler', k.off, { wert: href || '-' }); return; }\n                    sprachen.push({ code: (hl || '').toLowerCase(), href: href, off: k.off });\n                } else if (k.ns === NS_IMG) {\n                    if (k.lokal !== 'image') { b('ext_platz', 'fehler', k.off, { name: k.name }); return; }\n                    bilderHier++; zahlen.bilder++;\n                    var il = kind(k, NS_IMG, 'loc');\n                    if (!il || !textVon(il)) { b('bild_loc_fehlt', 'fehler', k.off); }\n                    else if (urlProbleme(textVon(il)).some(function (p) { return p === 'relativ' || p === 'schema'; })) { b('bild_url', 'fehler', il.off, { wert: textVon(il).slice(0, 120) }); }\n                    k.kinder.forEach(function (c) {\n                        if (c.ns === NS_IMG && \/^(caption|title|geo_location|license)$\/.test(c.lokal)) { b('bild_veraltet', 'hinweis', c.off, { name: c.name }); }\n                    });\n                } else if (k.ns === NS_VID) {\n                    if (k.lokal !== 'video') { b('ext_platz', 'fehler', k.off, { name: k.name }); return; }\n                    zahlen.videos++;\n                    videoPruefen(k, b);\n                } else if (k.ns === NS_NEWS) {\n                    if (k.lokal !== 'news') { b('ext_platz', 'fehler', k.off, { name: k.name }); return; }\n                    zahlen.news++;\n                    newsPruefen(k, b, jetzt);\n                } else if (\/sitemap-(image|video|news)|w3\\.org\\\/1999\\\/xhtml\/i.test(k.ns)) {\n                    b('ns_variante', 'fehler', k.off, { name: k.name, ns: k.ns });\n                } else {\n                    zahlen.fremdNs[k.ns || '-'] = (zahlen.fremdNs[k.ns || '-'] || 0) + 1;\n                }\n            });\n            if (bilderHier > 1000) { b('bild_zu_viele', 'fehler', e.off, { n: bilderHier }); }\n            if (sprachen.length && loc) {\n                var codes = {};\n                sprachen.forEach(function (sp) {\n                    if (codes[sp.code] !== undefined && codes[sp.code] !== sp.href) { b('hreflang_doppelt', 'fehler', sp.off, { wert: sp.code }); }\n                    codes[sp.code] = sp.href;\n                });\n                hrefs[loc] = sprachen.map(function (sp) { return sp.href; });\n                hreflangListen.push({ loc: loc, off: locK.off, sprachen: sprachen });\n            }\n        });<\/p>\n<p>        \/\/ hreflang: Selbstbezug und Rueckverweis innerhalb der Datei\n        if (hreflangListen.length) {\n            var extern = 0, rueckFehlt = 0, selbstFehlt = 0;\n            hreflangListen.forEach(function (h) {\n                var ziele = hrefs[h.loc];\n                if (ziele.indexOf(h.loc) === -1) { selbstFehlt++; b('hreflang_selbst', 'warnung', h.off, { wert: h.loc.slice(0, 120) }); }\n                h.sprachen.forEach(function (sp) {\n                    if (sp.href === h.loc) { return; }\n                    if (!gesehen[sp.href]) { extern++; return; }\n                    var zurueck = hrefs[sp.href];\n                    if (!zurueck || zurueck.indexOf(h.loc) === -1) { rueckFehlt++; b('hreflang_rueck', 'warnung', sp.off, { von: h.loc.slice(0, 120), nach: sp.href.slice(0, 120) }); }\n                });\n            });\n            if (extern) { b('hreflang_extern', 'hinweis', null, { n: extern }); }\n            if (!rueckFehlt && !selbstFehlt && !sammel.hreflang_code && !sammel.hreflang_doppelt) { b('hreflang_ok', 'gut', null, { n: hreflangListen.length }); }\n        }\n        if (zahlen.news > 1000) { b('news_zu_viele', 'fehler', null, { n: zahlen.news }); }<\/p>\n<p>        \/\/ Ueber die ganze Datei\n        var hostListe = Object.keys(zahlen.hosts);\n        if (!basis && hostListe.length > 1) { b('host_gemischt', 'warnung', null, { n: hostListe.length, liste: hostListe.slice(0, 4).join(', ') }); }\n        if (!basis && Object.keys(schemas).length > 1) { b('schema_gemischt', 'warnung', null, { http: schemas.http || 0, https: schemas.https || 0 }); }\n        zahlen.lastmodVerschieden = Object.keys(lastmodWerte).length;\n        if (eintraege.length) {\n            if (zahlen.mitLastmod === 0 && !sammel.lastmod_format) { b('lastmod_fehlt', 'hinweis'); }\n            else if (zahlen.mitLastmod < eintraege.length &#038;&#038; !sammel.lastmod_format) { b('lastmod_teil', 'hinweis', null, { mit: zahlen.mitLastmod, n: eintraege.length }); }\n            if (zahlen.mitLastmod >= 5 && zahlen.lastmodVerschieden === 1) { b('lastmod_gleich', 'hinweis', null, { wert: Object.keys(lastmodWerte)[0], n: zahlen.mitLastmod }); }\n        }\n        if (prio || cf) { b('prio_cf', 'hinweis', null, { priority: prio, changefreq: cf }); }\n        var fremd = Object.keys(zahlen.fremdNs);\n        if (fremd.length) { b('fremd_ns', 'hinweis', null, { liste: fremd.slice(0, 3).join(', ') }); }\n        var zaehlNoch = reihe.filter(function (f) { return f.stufe === 'fehler' || f.stufe === 'warnung'; }).length;\n        if (!zaehlNoch) { b('sauber', 'gut', null, { n: eintraege.length }); }\n        return ergebnis();\n    }<\/p>\n<p>    function videoPruefen(v, b) {\n        var fehlt = [];\n        ['thumbnail_loc', 'title', 'description'].forEach(function (n) { if (!textVon(kind(v, NS_VID, n))) { fehlt.push('video:' + n); } });\n        var cl = kind(v, NS_VID, 'content_loc'), pl = kind(v, NS_VID, 'player_loc');\n        if (!textVon(cl) && !textVon(pl)) { fehlt.push('video:content_loc \/ video:player_loc'); }\n        if (fehlt.length) { b('video_pflicht', 'fehler', v.off, { liste: fehlt.join(', ') }); }\n        var de = textVon(kind(v, NS_VID, 'description'));\n        if (de.length > 2048) { b('video_beschreibung', 'fehler', v.off, { n: de.length }); }\n        var du = kind(v, NS_VID, 'duration');\n        if (du && !(\/^\\d+$\/.test(textVon(du)) && +textVon(du) >= 1 && +textVon(du) <= 28800)) { b('video_dauer', 'fehler', du.off, { wert: textVon(du).slice(0, 20) }); }\n        var ra = kind(v, NS_VID, 'rating');\n        if (ra &#038;&#038; !(\/^\\d+(\\.\\d+)?$\/.test(textVon(ra)) &#038;&#038; +textVon(ra) <= 5)) { b('video_rating', 'fehler', ra.off, { wert: textVon(ra).slice(0, 20) }); }\n        ['publication_date', 'expiration_date'].forEach(function (n) {\n            var k = kind(v, NS_VID, n);\n            if (k &#038;&#038; datumArt(textVon(k)) !== 'ok') { b('video_datum', 'fehler', k.off, { name: 'video:' + n, wert: textVon(k).slice(0, 40) }); }\n        });\n        ['family_friendly', 'requires_subscription', 'live'].forEach(function (n) {\n            var k = kind(v, NS_VID, n);\n            if (k &#038;&#038; !\/^(yes|no)$\/.test(textVon(k))) { b('video_janein', 'fehler', k.off, { name: 'video:' + n, wert: textVon(k).slice(0, 20) }); }\n        });\n        ['restriction', 'platform'].forEach(function (n) {\n            kinderVon(v, NS_VID, n).forEach(function (k) {\n                if (!\/^(allow|deny)$\/.test(k.attrs.relationship || '')) { b('video_relationship', 'fehler', k.off, { name: 'video:' + n }); }\n                if (n === 'platform' &#038;&#038; !\/^(web|mobile|tv)(\\s+(web|mobile|tv))*$\/.test(textVon(k))) { b('video_platform', 'fehler', k.off, { wert: textVon(k).slice(0, 30) }); }\n            });\n        });\n        var tags = kinderVon(v, NS_VID, 'tag').length;\n        if (tags > 32) { b('video_tags', 'warnung', v.off, { n: tags }); }\n        var up = kind(v, NS_VID, 'uploader');\n        if (up && textVon(up).length > 255) { b('video_uploader', 'fehler', up.off, { n: textVon(up).length }); }\n        v.kinder.forEach(function (c) { if (c.ns === NS_VID && \/^(category|gallery_loc|price|tvshow)$\/.test(c.lokal)) { b('video_veraltet', 'hinweis', c.off, { name: c.name }); } });\n        if (pl && (pl.attrs.autoplay !== undefined || pl.attrs.allow_embed !== undefined)) { b('video_veraltet', 'hinweis', pl.off, { name: pl.name + ' @' + (pl.attrs.autoplay !== undefined ? 'autoplay' : 'allow_embed') }); }\n    }<\/p>\n<p>    function newsPruefen(nk, b, jetzt) {\n        var fehlt = [], pub = kind(nk, NS_NEWS, 'publication');\n        if (!pub) { fehlt.push('news:publication'); }\n        else {\n            if (!textVon(kind(pub, NS_NEWS, 'name'))) { fehlt.push('news:name'); }\n            var la = kind(pub, NS_NEWS, 'language');\n            if (!textVon(la)) { fehlt.push('news:language'); }\n            else if (!\/^([a-z]{2,3}|zh-cn|zh-tw)$\/.test(textVon(la))) { b('news_sprache', 'fehler', la.off, { wert: textVon(la).slice(0, 20) }); }\n        }\n        var pd = kind(nk, NS_NEWS, 'publication_date');\n        if (!textVon(pd)) { fehlt.push('news:publication_date'); }\n        else if (datumArt(textVon(pd)) !== 'ok') { b('news_datum', 'fehler', pd.off, { wert: textVon(pd).slice(0, 40) }); }\n        else if (datumMs(textVon(pd)) < jetzt - 2 * 86400000) { b('news_alt', 'warnung', pd.off, { wert: textVon(pd) }); }\n        if (!textVon(kind(nk, NS_NEWS, 'title'))) { fehlt.push('news:title'); }\n        if (fehlt.length) { b('news_pflicht', 'fehler', nk.off, { liste: fehlt.join(', ') }); }\n    }\n    \/\/ KERN-ENDE\n\n    \/\/ --- Darstellung -------------------------------------------------------------\n    function text(schluessel, werte) {\n        var vorlage = T[schluessel] === undefined ? schluessel : String(T[schluessel]);\n        return vorlage.replace(\/\\{(\\w+)\\}\/g, function (m, k) { return werte &#038;&#038; werte[k] !== undefined ? String(werte[k]) : m; });\n    }\n    function zahl(x) { return String(x).replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, T.tausender); }\n    function el(id) { return document.getElementById(id); }\n    function meldung(f) {\n        var d = Object.assign({}, f.daten);\n        Object.keys(d).forEach(function (k) { if (typeof d[k] === 'number') { d[k] = zahl(d[k]); } });\n        if (f.key === 'xml_kaputt') {\n            d.grund = text('xml_' + f.daten.code, d);\n            return text('b_xml_kaputt', d);\n        }\n        return text('b_' + f.key, d);\n    }\n    function zeile(tbody, name, wert) {\n        var tr = document.createElement('tr'), a = document.createElement('td'), c = document.createElement('td');\n        a.textContent = name; c.textContent = wert; c.className = 'sv-wert';\n        tr.appendChild(a); tr.appendChild(c); tbody.appendChild(tr);\n    }\n    function status(t, schlecht) { var s = el('sv-status'); s.textContent = t; s.className = 'sv-status' + (schlecht ? ' sv-schlecht' : ''); }\n\n    function zeigen(r, quelleText) {\n        var z = r.zahlen, tb = el('sv-zahlen'), ul = el('sv-befunde');\n        tb.textContent = ''; ul.textContent = '';\n        zeile(tb, T.z_art, z.art === 'index' ? T.art_index : (z.art === 'urlset' ? T.art_urlset : '\u2013'));\n        zeile(tb, z.art === 'index' ? T.z_sitemaps : T.z_eintraege, zahl(z.eintraege));\n        zeile(tb, T.z_groesse, text('groesse_wert', { kb: zahl(Math.round(z.bytes \/ 1024)), anteil: (z.bytes \/ MAX_BYTES * 100).toFixed(1).replace('.', T.dezimal) }));\n        var hosts = Object.keys(z.hosts);\n        zeile(tb, T.z_hosts, hosts.length ? hosts.slice(0, 4).join(', ') + (hosts.length > 4 ? ' \u2026' : '') : '\u2013');\n        if (z.eintraege) { zeile(tb, T.z_lastmod, text('lastmod_wert', { mit: zahl(z.mitLastmod), n: zahl(z.eintraege), verschieden: zahl(z.lastmodVerschieden) })); }\n        if (z.art === 'urlset') { zeile(tb, T.z_erweiterungen, text('erw_wert', { hreflang: zahl(z.hreflang), bilder: zahl(z.bilder), videos: zahl(z.videos), news: zahl(z.news) })); }\n        zeile(tb, T.z_urteil, text('urteil_' + r.urteil, r.stufen));\n        r.befunde.forEach(function (f) {\n            var li = document.createElement('li'), marke = document.createElement('span'), inhalt = document.createElement('span');\n            marke.className = 'sv-marke sv-' + f.stufe; marke.textContent = T['stufe_' + f.stufe];\n            inhalt.textContent = meldung(f);\n            if (f.zeilen && f.zeilen.length) {\n                var zl = document.createElement('span');\n                zl.className = 'sv-zeilen';\n                zl.textContent = text(f.n > 1 ? 'zeilen_mehr' : 'zeilen_eine', { liste: f.zeilen.join(', ') + (f.n > f.zeilen.length ? ' \u2026' : ''), n: zahl(f.n) });\n                inhalt.appendChild(zl);\n            } else if (f.n > 1) {\n                var zn = document.createElement('span'); zn.className = 'sv-zeilen'; zn.textContent = text('anzahl', { n: zahl(f.n) }); inhalt.appendChild(zn);\n            }\n            li.appendChild(marke); li.appendChild(inhalt); ul.appendChild(li);\n        });\n        el('sv-ergebnis').hidden = false;\n        status(quelleText || '', false);\n    }<\/p>\n<p>    function los(quelleText) {\n        var s = el('sv-xml').value;\n        if (!\/\\S\/.test(s)) { el('sv-ergebnis').hidden = true; status(T.s_leer, true); return null; }\n        var r = pruefen(s, { datei: el('sv-adresse').value.trim() });\n        zeigen(r, quelleText);\n        return r;\n    }\n    \/\/ Grosse Dateien: erst die Statuszeile zeichnen lassen, dann rechnen\n    function losSpaeter(quelleText) {\n        if (el('sv-xml').value.length > 2000000) { status(T.s_pruefe, false); setTimeout(function () { los(quelleText); }, 30); }\n        else { los(quelleText); }\n    }<\/p>\n<p>    function dateiLesen(datei) {\n        if (!datei) { return Promise.resolve(null); }\n        if (datei.size > 60 * 1048576) { status(T.s_zu_gross, true); return Promise.resolve(null); }\n        status(T.s_lese, false);\n        return datei.slice(0, 2).arrayBuffer().then(function (kopf) {\n            var k = new Uint8Array(kopf), gz = k[0] === 0x1f && k[1] === 0x8b;\n            if (gz && typeof DecompressionStream === 'undefined') { throw new Error('gz'); }\n            var strom = gz ? datei.stream().pipeThrough(new DecompressionStream('gzip')) : datei.stream();\n            return new Response(strom).arrayBuffer().then(function (buf) {\n                if (buf.byteLength > 60 * 1048576) { throw new Error('gross'); }\n                var txt;\n                try { txt = new TextDecoder('utf-8', { fatal: true }).decode(buf); }\n                catch (e) { throw new Error('utf8'); }\n                el('sv-xml').value = txt;\n                return los(text(gz ? 's_datei_gz' : 's_datei', { name: datei.name, kb: zahl(Math.round(buf.byteLength \/ 1024)) }));\n            });\n        }).catch(function (e) {\n            el('sv-ergebnis').hidden = true;\n            status(e.message === 'utf8' ? T.s_utf8 : (e.message === 'gross' ? T.s_zu_gross : T.s_lesefehler), true);\n            return null;\n        });\n    }<\/p>\n<p>    var BEISPIEL = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n' +\n        '<urlset xmlns=\"http:\/\/www.sitemaps.org\/schemas\/sitemap\/0.9\"\\n' +\n        '        xmlns:xhtml=\"http:\/\/www.w3.org\/1999\/xhtml\"\\n' +\n        '        xmlns:image=\"http:\/\/www.google.com\/schemas\/sitemap-image\/1.1\">\\n' +\n        '  <url>\\n' +\n        '    <loc>https:\/\/example.com\/en\/pricing\/<\/loc>\\n' +\n        '    <lastmod>2026-09-28<\/lastmod>\\n' +\n        '    <xhtml:link rel=\"alternate\" hreflang=\"en\" href=\"https:\/\/example.com\/en\/pricing\/\"\/>\\n' +\n        '    <xhtml:link rel=\"alternate\" hreflang=\"de\" href=\"https:\/\/example.com\/de\/preise\/\"\/>\\n' +\n        '    <image:image><image:loc>https:\/\/example.com\/img\/plans.png<\/image:loc><image:caption>Plans<\/image:caption><\/image:image>\\n' +\n        '  <\/url>\\n' +\n        '  <url>\\n' +\n        '    <loc>https:\/\/example.com\/de\/preise\/<\/loc>\\n' +\n        '    <lastmod>2026-09-28T14:05<\/lastmod>\\n' +\n        '    <xhtml:link rel=\"alternate\" hreflang=\"de\" href=\"https:\/\/example.com\/de\/preise\/\"\/>\\n' +\n        '  <\/url>\\n' +\n        '  <url>\\n' +\n        '    <loc>\/en\/contact\/<\/loc>\\n' +\n        '    <priority>1.5<\/priority>\\n' +\n        '  <\/url>\\n' +\n        '  <url>\\n' +\n        '    <loc>https:\/\/example.com\/en\/pricing\/<\/loc>\\n' +\n        '    <changefreq>sometimes<\/changefreq>\\n' +\n        '  <\/url>\\n' +\n        '<\/urlset>\\n';<\/p>\n<p>    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.SITEMAP = { T: T, xmlLesen: xmlLesen, pruefen: pruefen, datumArt: datumArt, urlProbleme: urlProbleme, hreflangGueltig: hreflangGueltig,\n        meldung: meldung, los: los, BEISPIEL: BEISPIEL };<\/p>\n<p>    if (!el('sv-wurzel') || !el('sv-xml')) { return; }\n    el('sv-los').addEventListener('click', function () { losSpaeter(''); });\n    el('sv-beispiel').addEventListener('click', function () { el('sv-xml').value = BEISPIEL; el('sv-adresse').value = 'https:\/\/example.com\/sitemap.xml'; los(T.s_beispiel); });\n    el('sv-leeren').addEventListener('click', function () { el('sv-xml').value = ''; el('sv-adresse').value = ''; el('sv-datei').value = ''; el('sv-ergebnis').hidden = true; status('', false); });\n    el('sv-datei').addEventListener('change', function () { dateiLesen(this.files && this.files[0]); });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Checks an XML sitemap or sitemap index in the browser against sitemaps.org and Google&#8217;s extensions: well-formedness with line and column, namespaces, required fields, lastmod, limits, hreflang with return links, and image, video and news tags.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[91297,91094,92757],"class_list":["post-20961","page","type-page","status-publish","hentry","tag-data-quality","tag-seo","tag-web-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Sitemap Checker &amp; Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Sitemap Checker &amp; Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Checks an XML sitemap or sitemap index in the browser against sitemaps.org and Google&#039;s extensions: well-formedness with line and column, namespaces, required fields, lastmod, limits, hreflang with return links, and image, video and news tags.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-01T16:29:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/sitemap-checker-validator-schema-hreflang-image-video-news\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/sitemap-checker-validator-schema-hreflang-image-video-news\\\/\",\"name\":\"Sitemap Checker & Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-01T16:14:10+00:00\",\"dateModified\":\"2026-10-01T16:29:19+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/sitemap-checker-validator-schema-hreflang-image-video-news\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/sitemap-checker-validator-schema-hreflang-image-video-news\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/sitemap-checker-validator-schema-hreflang-image-video-news\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Sitemap Checker &#038; Validator: Schema, hreflang, Image, Video and News Extensions\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Sitemap Checker & Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/","og_locale":"en_US","og_type":"article","og_title":"Sitemap Checker & Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik","og_description":"Checks an XML sitemap or sitemap index in the browser against sitemaps.org and Google's extensions: well-formedness with line and column, namespaces, required fields, lastmod, limits, hreflang with return links, and image, video and news tags.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-10-01T16:29:19+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/","name":"Sitemap Checker & Validator: Schema, hreflang, Image, Video and News Extensions | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-10-01T16:14:10+00:00","dateModified":"2026-10-01T16:29:19+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/sitemap-checker-validator-schema-hreflang-image-video-news\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"Sitemap Checker &#038; Validator: Schema, hreflang, Image, Video and News Extensions"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=20961"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20961\/revisions"}],"predecessor-version":[{"id":20973,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20961\/revisions\/20973"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20961"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}