XSLT Extensions

I wrote yesterday about using PowerShell to try out things interactively in XPath, with the goal of doing some work on my blog publishing program.

At some point, however, I need to get the date of my posts based off their filename. To do this, I either need to do a whole lot of string manipulation, which is clumsy to do in XPath, or I can use something like regular expressions.

To be fair, one thing I dislike in general about languages without variables is the inability to name my indices when doing string manipulation, leading to repeated (and typo-prone) search expression. I'm looking at you too, off-the-shelf SQL.

Anyway, once I need to start coding for real, Visual Studio is pretty great, so I can quickly come up with this. Note that my XSLT will have a document with a reference to all posts with an absolute-filename attribute on posts, which is what I'll be looking at.

public class XsltExtensions
{
  public const string Namespace = "http://www.lopezruiz.net/xslt-extensions/1.0";
  public readonly DateTime Today = DateTime.Today;
  public readonly Regex PostDateRegex = new Regex(@"\\(\d\d\d\d)\\(\d\d)\\(\d\d)-");

  public bool IsPostInPast(XPathNavigator nodes)
  {
    Match match;
    if (nodes != null && nodes.NodeType == XPathNodeType.Element && 
        null != (match = PostDateRegex.Match(nodes.GetAttribute("absolute-filename", ""))) &&
        match.Success)
    {
      int year, month, day;
      if (!Int32.TryParse(match.Groups[1].Value, out year)) return false;
      if (!Int32.TryParse(match.Groups[2].Value, out month)) return false;
      if (!Int32.TryParse(match.Groups[3].Value, out day)) return false;
      if (new DateTime(year, month, day) <= Today)
      {
        return true;
      }
    }
    return false;
  }
}

Armed with this, I can now include my extensions in my XSLT processing code.

XsltArgumentList argumentList = new XsltArgumentList();
argumentList.AddExtensionObject(XsltExtensions.Namespace, new XsltExtensions());
// ...
transform.Transform(input, arguments, xmlWriter, null);
    

And then, whenever I want to check whether a post should be visible, I can do a simple check.

  <xsl:for-each select='$posts/main[ext:IsPostInPast(.)]'>
    ...

This makes it pretty easy to add more interesting functionality, but I can do my prep work with something more interactive.

Enjoy!

Tags:  xmlxslt

Home