{localLinks}
Overview
On a recent project we stumbled into an interesting problem. We
had been asked to build a very simple website, however we wanted to
allow the site to grow and develop so making it as flexible as
possible was paramount. The site would have monthly publications
which could contain 'assets'. It was likely the 'assets' would be
used in future publications so we wanted to store these in their
own folder.
The publication would show a preview of the asset & when it
was clicked the asset would play at the top of the publication.
This was done by passing the nodeID of the asset into the
querystring of the publication page. The publication also showed a
teaser which was associated to the asset.
This gave our client a very flexible solution. However our
clients wanted to be able to link to other assets within the teaser
(contentTeaser) field.
This presented us with a problem, the content editor could link
to other assets. But when this link was parsed it would link to the
other document. This was not the behavior we wanted, we wanted to
access the nodeID and pass this in the query string to keep
behavior uniform.
-
To do this we needed to interupt how Umbraco parsed the XML by
Encoding the 'contentTeaser', accessing the link information,
replacing it, and then decoding the data so it would be suitable
for front-end render again.
We did this using XSLT, eXSLT, Regex and some C#.
References
our.Umbraco.org - Extend your XSLT with Custom Functions
eXSLT.org
- Regex Replace
eXSLT.org - Regex Match (more
useful examples)
our.Umbraco.org
- Umbraco Library
The Code
This document has been broken down into six sections, at the
bottom of this page is a link to download the XSLT.
- Custom XSLT Function
- Get the $currentPage URL
- Get the $currentPage Content and Encode (variable)
- Set the Regex String Replacement
- Run Regex Replace
- Get the Replace Output, Decode & Display.
1. Custom XSLT
This code has been referenced from the Umbraco Wiki you can find
it here.
<msxml:script
implements-prefix="htmlDecode" language="C#">
<msxml:assembly name="System.Web"/>
<msxml:using namespace="System.Web"/>
<![CDATA[ public string convertText(string text) { string
decodedStr = HttpUtility.HtmlDecode(text); return decodedStr; }
]]>
</msxml:script>
2. Get the $currentPage URL
We need the URL for the page we want to make the links reference
too.
Using the 'umbraco.library:NiceURL(string)' function.
This URL is assigned the variable '$niceURL'.
<xsl:variable
name="niceURL">
<xsl:value-of
select="umbraco.library:NiceUrl($currentPage/@id)"/>
</xsl:variable>
3. Get the $currentPage Content and Encode
(variable)
Next we grab the content which contains our links. In this case
the datatype was a richtext editor. To be able to process this with
the eXSLT:Regex extension we needed to encode the characters in the
HTML.
This is really easy to do using the
'umbraco:library:HtmlEncode(string)' function.
<xsl:variable
name="assetTeaser">
<xsl:value-of select="umbraco.library:HtmlEncode(data [@alias =
'assetTeaser'])"/> </xsl:variable>
4. Set the Regex String Replacement
For some reason I couldn't write the whole replacement string in
the regex replace function. So I pull in the string I wanted by
setting it as a variable. In anyone knows how to fix this please
let me know!
<xsl:variable
name="niceURLregex">
..<xsl:value-of select="$niceURL"/>
?clip=$1
</xsl:variable>
5. Run Regex Replace
Using a eXSLT function called replace would can feed in our
content, find the {localLinks} and then replace these with the
variable we set earlier.
in this case, we are looking for localLink and a 4 digit number.
Its worth noting the number could be longer than four digits if
your site has many nodes. We also inform the processor that it is
dealing with a multiline input (m), a ungreedy pattern (U) and to
treat each string as a single line (s); giving us 'mUs'.
We now need to feed the function the replacement information. As
noted above I could not find a way to write what is stored in the
variable directly. Because of this we simply pull the variable
in.
This string tells is to;
- .. - move to the root.
- $niceURL - get the niceURL variable, defined in the top of the
document. This is just the URL for the current page.
- ?clip= - add some static text
- $1 - add the string, e.g "1234" in /{localLink:(1234)}
<xsl:variable name="assetTeaserReplace">
<xsl:value-of
select="Exslt.ExsltRegularExpressions:replace($assetTeaser,
'/{localLink:([0-9][0-9][0-9][0-9])}', 'mUs', $niceURLregex )"
disable-output-escaping="no" /> </xsl:variable>
6. Get Replace Output, Decode and Display
Okay so we've taken $assetTeaser, and using some regex we've
updated the links. Now we need to Decode it. (we encoded it to
start with). Its at this point we run the custom function we
set at the top of the document which gives us the capability to
decodeHTML.
<xsl:value-of
select="htmlDecode:convertText(string($assetTeaserReplace))"
disable-output-escaping="yes" />
-
You
can download the XSLT for this here.