Fully-qualifed URL is incorrectly being coerced to a relative URL

Topics: User Forum
Jan 10, 2013 at 9:12 PM
Edited Jan 10, 2013 at 9:14 PM

I just took the plunge to update to the latest Sandcastle and SHFB after going a couple years on an earlier version. The resultant generated website came out very good, but not quite perfect.

I include a footer (in SHFB's "Additional footer content" field) that begins thusly:

<div>Copyright (C) 2001-2012 Michael Sorens -- Revised 2012.12.10
<a href='http://sourceforge.net/projects/cleancode'>
<
img src='http://sflogo.sourceforge.net/sflogo.php?group_id=101363&type=9' width='80' height='15' border='0' alt='Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads'/></a></div> <script type='text/javascript' src='/js/MenuArchive.js'></script> . . .

Notice that the img element includes a fully-qualified URL. After running through SHFB the final HTML fragment looks like this (I have added line breaks for readability):

<div id="OH_footer" class="OH_footer"><p>
<div>Copyright (C) 2001-2012 Michael Sorens -- Revised 2012.12.10 <img src="./../icons/online_icon.gif" class="OH_offlineIcon" alt="Online" title="Online" />
<a href="http://sourceforge.net/projects/cleancode" target="_blank">
<
img src="./http://sflogo.sourceforge.net/sflogo.php?group_id=101363&type=9" width="80" height="15" border="0"
alt="Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a></div>
<script type="text/javascript" src="/js/MenuArchive.js"><!----></script>
. . .

Notice that the image URL went from "http://..." to "./http://...", i.e. it was turned into some sort of mongrel relative URL.

I collected a few other observations that may help in diagnosing this issue. From a global search on the generated web sites I find:

  1. There are many instances of src="./http" present--presumably all from this issue.
  2. There are no instances of src="http".
  3. There are many instances of href="http" (i.e. from "a" elements).
  4. There are no instances of href="./http".

Note that these are observations of the output (the generated HTML); I have not correlated these to what I actually have present in my source files.

System details:

  • Installation: Sandcastle 2.7.2.0 and SHFB 1.9.6.0 via guided installer
  • OS: Windows 8/64
  • Presentation style: VS2010
  • Output type: website

Coordinator
Jan 11, 2013 at 4:23 PM

The problem is in the VS2010\branding\ps-body.xslt file.  If you replace the "ps-img" template at the very end of the file with this one, it will fix it:

  <!-- redirect image sources to the appropriate path -->
  <xsl:template match="xhtml:img" name="ps-img">
    <xsl:copy>
      <xsl:choose>
        <xsl:when test="not($pre-branding)">
          <xsl:for-each select="@*">
            <xsl:choose>
              <xsl:when test="name()='src'">
                <xsl:attribute name="src">
                  <xsl:choose>
                    <xsl:when test="$downscale-browser">
                      <xsl:choose>
                        <xsl:when test="starts-with(.,'http:') or starts-with(.,'https:')">
                          <xsl:value-of select="."/>
                        </xsl:when>
                        <xsl:otherwise>
                          <xsl:value-of select="branding:BackslashesToFrontslashes(concat($contentFolder,'/',.))"/>
                        </xsl:otherwise>
                      </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                      <xsl:value-of select="branding:BuildContentPath($contentFolder,.)"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:apply-templates select="."/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="@*"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

Eric

 

Jan 11, 2013 at 11:01 PM
Edited Jan 11, 2013 at 11:02 PM

Thanks, Eric, that fixed my particular test case. Reading your XSLT, though, I think you might also want to include one additional predicate on the test, checking for beginning with a virgule, another form of absolute URL (technically a URL relative to the server root), i.e.

test="starts-with(.,'http:') or starts-with(.,'https:') or starts-with(.,'/')"

That would cover the test case of a URL such as "/my/absolute/url/path/image.gif".

 

Coordinator
Jan 12, 2013 at 3:13 AM

I added the extra check.  Thanks.

Eric