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!