preserveWhiteSpace = false; $dom->formatOutput = true; // Enable internal error handling $previous_libxml_setting = libxml_use_internal_errors( true ); // Check XML errors if ( ! $dom->loadXML( $content ) ) { if ( defined( 'WPLNG_DEBUG_XML' ) && true === WPLNG_DEBUG_XML ) { $errors = array(); foreach ( libxml_get_errors() as $error ) { $errors[] = $error->message; } libxml_clear_errors(); $debug = array( 'title' => 'wpLingua XML debug - Invalid XML content', 'errors' => $errors, ); error_log( var_export( $debug, true ) ); } return $content; } // Restore previous setting libxml_use_internal_errors( $previous_libxml_setting ); // Replace XSL stylesheet URL if option enabled if ( get_option( 'wplng_sitemap_xsl_override', false ) ) { $wplng_xsl_url = plugins_url( 'assets/sitemap.xsl', __DIR__ ); // Find existing xml-stylesheet processing instruction $xsl_found = false; foreach ( $dom->childNodes as $node ) { if ( $node->nodeType === XML_PI_NODE && $node->target === 'xml-stylesheet' ) { $node->data = 'type="text/xsl" href="' . esc_url( $wplng_xsl_url ) . '"'; $xsl_found = true; break; } } // If no xml-stylesheet found, add one before the root element if ( ! $xsl_found ) { $xsl_pi = $dom->createProcessingInstruction( 'xml-stylesheet', 'type="text/xsl" href="' . esc_url( $wplng_xsl_url ) . '"' ); $dom->insertBefore( $xsl_pi, $dom->documentElement ); } } $signature = '' . PHP_EOL; // Register namespaces and prepare XPath. $xpath = new DOMXPath( $dom ); $xpath->registerNamespace( 'sm', 'http://www.sitemaps.org/schemas/sitemap/0.9' ); $xpath->registerNamespace( 'xhtml', 'http://www.w3.org/1999/xhtml' ); // Ensure the root element declares the required namespaces. $urlset = $dom->documentElement; if ( ! $urlset->hasAttribute( 'xmlns' ) ) { $urlset->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' ); } if ( ! $urlset->hasAttribute( 'xmlns:xhtml' ) ) { $urlset->setAttribute( 'xmlns:xhtml', 'http://www.w3.org/1999/xhtml' ); } // Get all nodes. $url_nodes = $xpath->query( '//sm:url' ); if ( empty( $url_nodes ) ) { return $dom->saveXML() . $signature; } foreach ( $url_nodes as $url_node ) { // Get original URL. $loc_node = $xpath->query( 'sm:loc', $url_node )->item( 0 ); if ( empty( $loc_node ) ) { continue; } $url_original = trim( $loc_node->nodeValue ); if ( '' === $url_original || ! wplng_url_is_translatable( $url_original ) ) { continue; } // Add link for original language. $link_node = $dom->createElement( 'xhtml:link' ); $link_node->setAttribute( 'rel', 'alternate' ); $link_node->setAttribute( 'hreflang', esc_attr( $language_website_id ) ); $link_node->setAttribute( 'href', esc_url( $url_original ) ); $url_node->appendChild( $link_node ); // Add links for target languages. foreach ( $languages_target_ids as $language_id ) { $translated_url = wplng_url_translate( $url_original, $language_id ); // Validate the translated URL. if ( empty( $translated_url ) || ! filter_var( $translated_url, FILTER_VALIDATE_URL ) ) { continue; } $link_node = $dom->createElement( 'xhtml:link' ); $link_node->setAttribute( 'rel', 'alternate' ); $link_node->setAttribute( 'hreflang', esc_attr( $language_id ) ); $link_node->setAttribute( 'href', esc_url( $translated_url ) ); $url_node->appendChild( $link_node ); } } $sitemap = $dom->saveXML(); if ( empty( $sitemap ) ) { return $content; } return $sitemap . $signature; } /** * Modify XSL stylesheet to display translated links in sitemap. * * @param string $content The original XSL content. * @return string The modified XSL content with translations displayed under each URL. */ function wplng_sitemap_modify_xsl( $content ) { if ( empty( $content ) ) { return $content; } // Check if this XSL already has translations support if ( strpos( $content, 'wplng-translations' ) !== false ) { return $content; } // Load XSL into DOMDocument $dom = new DOMDocument( '1.0', 'UTF-8' ); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; // Enable internal error handling $previous_libxml_setting = libxml_use_internal_errors( true ); if ( ! $dom->loadXML( $content ) ) { libxml_clear_errors(); libxml_use_internal_errors( $previous_libxml_setting ); return $content; } libxml_use_internal_errors( $previous_libxml_setting ); $xpath = new DOMXPath( $dom ); $xpath->registerNamespace( 'xsl', 'http://www.w3.org/1999/XSL/Transform' ); // Add xhtml namespace to xsl:stylesheet if not present $stylesheet = $dom->documentElement; if ( ! $stylesheet->hasAttribute( 'xmlns:xhtml' ) ) { $stylesheet->setAttribute( 'xmlns:xhtml', 'http://www.w3.org/1999/xhtml' ); } // Add CSS to existing