xelco52
xelco52

Reputation: 5347

XSLT to convert relative to absolute image paths

I'm having difficulty conceptualizing how to go about converting an image's relative path to an absolute path via xslt.

There currently exists an XML document that has a section <myHTML> which holds html encoded text. This html document may contain <img> tags with relative paths - For example: <img src="myPic.jpg>

There also exists a xsl that processes that section with a block like this:

<div id="bodyText">
  <xsl:value-of select="/abc:myT/abc:myHTML" disable-output-escaping="yes">
</div>

I need to prepend an absolute path to the beginning of the image name. Since the whole html block is being accessed via value-of select, I'm not sure how to attack this.

I do believe that I need to use an xsl input parameter in order to pass in the path, but not sure how to access the <img> tag inside <myHTML>.

And advice would be appreciated.

Update

There were some questions as to the format of the XML file and what I meant by "html encoded text". Please disregard typos, the below chunk is from memory and is representative of the actual xml file. It is meant to illustrate the HtmlEncode() data in the <myHTML> block.

<?xml version="1.0" encoding="UTF-8">
<?xml-stylesheet ...snipped..>
<myT xmlns="abc">
   <myHTML>
      &lt;html$gt;&lt;head$gt;&lt;title$gt;This is my title&lt;/title$gt;&lt;/head$gt;
      &lt;body$gt;
      &lt;img src="myPic.jpg" /$gt;
      &lt;/body$gt;&lt;/html$gt;
   </myHTML>
</myT>

Additionally, as Dimitre pointed out, i'm using .NET and it's XSLT 1.0 processor.

Upvotes: 2

Views: 2404

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243569

This complete and short and working transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:abc="some:abc" exclude-result-prefixes="abc">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pBase" select="'http://www.copm.com/'"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="abc:img[@src]">
  <xsl:element name="img" namespace="some:abc">
   <xsl:attribute name="src">
     <xsl:value-of select="concat($pBase, @src)"/>
   </xsl:attribute>
   <xsl:apply-templates select="@*[not(name()='src')]|node()"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when applied on the following XML document:

<myT xmlns="some:abc">
    <myHTML>
        <img src="myPic.jpg"/>
    </myHTML>
</myT>

produces the wanted, correct result (any src attribute of an img element is converted to absolute, using the provided as parameter base):

<myT xmlns="some:abc">
   <myHTML>
      <img src="http://www.copm.com/myPic.jpg"/>
   </myHTML>
</myT>

Update:

As noted by Michael Kay, in XSLT 2.0 and later one should use the standard XPath 2.0 function resolve-uri().

However, from comments of the OP it has become clear that he is using a .NET XSLT processor, which means an XSLT 1.0 processor.

Upvotes: 1

wst
wst

Reputation: 11771

Once you use xsl:value-of, you're working with a string. So you could use a regex, but that seems shaky. Why not just use a template?

<!-- XSL input param -->
<xsl:param name="absolute-path" select="'http://default-path/"></xsl:param>

...

<div id="bodyText">
  <xsl:apply-templates select="/abc:myT/abc:myHTML/node()"/>
</div>

...

<xsl:template match="abc:img">
  <img>
     <xsl:attribute name="src">
         <xsl:value-of select="concat($absolute-path,@src)"/>
     </xsl:attribute>
     <xsl:copy-of select="@* except @src"/>
  </img>
</xsl:template>

<xsl:template match="text()">
  <xsl:copy />
</xsl:template>

Upvotes: 0

Dominic Cronin
Dominic Cronin

Reputation: 6201

Unless there is a good reason forcing you to use XLST for this, I'd suggest that it's the wrong tool for the job. Load the XML document into a DOM and XPath to get a node-set containing the relevant myHtml elements. Unescape the HTML and load it into an HTML parser (or if it's XHTML, an XML parser).. again XPath to get the img element, and read/write the href attributes.

In any case - it might help if you could update the question with more details of your problem. Are there constraints forcing you to use XSLT? (In which case, is the HTML escaped in a way that you could reliably regex against?) Is performance an issue? What sort of application is it? Etc. Etc.

Upvotes: 2

Related Questions