Wordpress-seo: XSL stylesheet inline

Created on 19 Dec 2017  路  7Comments  路  Source: Yoast/wordpress-seo

xml sitemap

Most helpful comment

For context:

This should fix a large amount of issues related to the XML sitemap being blank because the XSLT doesn't load. Additionally, this fixes a performance issue as we don't have to boot WordPress twice for an XML sitemap view.

All 7 comments

For context:

This should fix a large amount of issues related to the XML sitemap being blank because the XSLT doesn't load. Additionally, this fixes a performance issue as we don't have to boot WordPress twice for an XML sitemap view.

I've tried the suggested situation and was not able to get something that works:

  1. I've put the style inline, it was applied, but not correctly because of the xpath queries that covers both situations.
  2. When you are using the stylesheet inline I've found out that you have to put the sitemap xml within the stylesheet tags. I think this has to do with letting the stylesheet know where the styles should be applied to.
  • This <xsl:if test="count(/sitemapindex/sitemap) &lt; 1"> should be rewritten to get it working with the inline stylesheet.
  • We should change the way how the sitemap is rendered.
  • I think the solution might have something to do with namespaces in the xml. But I am not sure.
  • I didn't verified if the sitemap is still valid when the xml has been places inside of the stylesheet.

I've committed the branch:8521-load-xml-stylesheet-inline

This is the first example I've tried to get context on how an inline stylesheet should work.

<?xml version="1.0" encoding="utf-8"?>
<!--Reference the file name as the href value-->
<?xml-stylesheet type="text/xsl" href=""?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
>

    <!-- Output HTML doctype with text/html content-type and without XML declaration-->
    <xsl:output method="xml" encoding="utf-8" version="" indent="yes" standalone="no" media-type="text/html" omit-xml-declaration="yes" doctype-system="about:legacy-compat" />


    <!-- Read the children of the stylesheet itself -->
    <xsl:template match="xsl:stylesheet">
        <xsl:apply-templates/>
    </xsl:template>

    <!-- Output the HTML markup-->
    <xsl:template match="/">
        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
            </head>
            <body>
                <div class="foo">
                    <span class="bar">
                        <span class="baz">1</span>
                    </span>
                    <!--Added comment to fill empty node-->
                    <span class="placeholder"><xsl:comment/></span>
                </div>

                <!-- Read matching templates -->
                <xsl:apply-templates />
                <!--Add comment to fill empty script tag-->
                <script src="foo.js" type="application/x-javascript"><xsl:comment/></script>
            </body>
        </html>
    </xsl:template>

    <!-- Don't reprint text nodes within the xsl:stylesheet node -->
    <xsl:template match="text()"/>

    <!-- Read non-namespaced nodes within the xsl:stylesheet node -->
    <xsl:template match="//node()[local-name() = name()]">
        <xsl:if test="local-name() = 'foo'">
            <xsl:variable name="foo" select="."/>

            <input type="text" id="{$foo}" value="{$foo}"></input>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:template>

    <test>
        <foo>A</foo>
        <foo>B</foo>
        <foo>C</foo>
    </test>

</xsl:stylesheet>

It seems that the XML Sitemap ruleset prevents the root element (sitemapindex etc) from being embedded inside a xml:template element.

As this works for generic XML files, applying it to Sitemaps proofs rather difficult.

@jrfnl do you have any additional insights on possibilities to provide this functionality, or why it will not work?

do you have any additional insights on possibilities to provide this functionality, or why it will not work?

@moorscode Not off the top of my head. I'd need to do some research myself.

It seems that the XML Sitemap ruleset prevents the root element (sitemapindex etc) from being embedded inside a xml:template element.

Could you expand on this a bit ? What do you mean by _Sitemap ruleset_ ? Do you mean the DTD ?

Additionally, this fixes a performance issue as we don't have to boot WordPress twice for an XML sitemap view.

That is one thing which I've often wondered about too and which I think could be solved quite easily.
In the WPSEO XSL file, there are only five PHP calls.
Two of which are shortlinks to the Yoast site and three are URLs which need to take the site in which the file is being used into account.

All of this could be "hard-coded"/cached. I.e. on install, the file could be generated based on the current file as template and written to disk.
On upgrade of WPSEO, update of the home_url and possibly in a weekly cronjob or something, the file on disk could be regenerated to make sure it is in sync.
This action could also be added to the queue for when the sitemaps are completely regenerated on demand from the dashboard.
A note should be made in the docs that if someone uses constants in the wp-config file to define the PLUGIN_URL or INCLUDE_URL, that if those are updated, the user should regenerate the sitemaps.

Would that help ?

We currently load the XLS via a registered route - see https://github.com/Yoast/wordpress-seo/blob/trunk/inc/sitemaps/class-sitemaps-router.php#L34

This means that we are loading the entire WordPress environment to be able to render the stylesheet.

The proposed solution is to determine if we can directly load the file, instead of going through WordPress. As WordPress .htaccess configuration by default has the entries to not rewrite files or directories that exist to index.php.

Pieces of PHP that need to be determined if they can be generated without having the WordPress context:

  • <?php echo esc_url( home_url( 'sitemap_index.xml' ) ); ?> reference

    • No way of knowing for sure what this path is, if the installation is a (multisite) subdirectory install.

    • Removing this reference could be an option to resolve the problem. Thus is reducing usability for the feature.

  • <?php echo esc_url( includes_url( 'js/jquery/jquery.js' ) ); ?> -
    reference

    • Adding jQuery to the plugin would make sure we can know the path (relative to the requested path).

  • <?php echo esc_url( plugins_url( 'js/dist/jquery.tablesorter.min.js', WPSEO_FILE ) ); ?>
    reference

    • [x] This can be converted to relative path.

  • 2x shortlink calls. These are only adding the version number as UTM tag, and are not required to be passed through the helper.

    • <?php echo esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1y5' ) ) ?>

    • <?php echo esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1y6' ) ) ?>

@moorscode
Re point 1: let's remove it. Too much of a cost for too little gain.
Re points 2 and 3 above: I'm very ok with removing the sorting script altogether. Too much of a cost for too little gain.
Point 4 then is an easy fix.

Basically this means this can become a static XSL file, as discussed with @moorscode yesterday.

Was this page helpful?
0 / 5 - 0 ratings