Selecting a CSS class with XPath

While looking for a way to select a CSS class with XPath in a reliable way. I came across many solutions, and while they felt obvious, they were flawed as well. So lets start with the most reliable way I found so far.

How do you do this in XPath?

XPath doesn’t have a native equivalent of a CSS class selector. Where .className will select any element that has the class className. The closest equivalent is:

//*[contains(concat(" ", normalize-space(@class), " "), " className ")]

The function normalize-space strips leading and trailing whitespace and also replaces sequences of whitespace characters by a single space.

Similiarly it is equivalent to the CSS selector:


which will match any element whose class attribute value is a list of whitespace-separated values, one of which is exactly equal to className.

The obvious but wrong ways to do it

The XPath selector:


doesn’t work because it won’t match an element that has more than one class, for example

<div class="className anotherClassName">

It also won’t match if there is any extra whitespace around the class name:

<div class=" className  ">

The ‘improved’ XPath selector:

//*[contains(@class, "className")]

doesn’t work either because it wrongly matches elements with the class classNameTwo, for example:

<div class="classNameTwo">

How to remove the Category Base from WordPress paths

Every now and then I get asked how to get rid of the “category” base from their WordPress URL so that becomes

The Simple Solution

Luckily, there’s a plugin that can do this for you named FV Top Level Categories with no hassles or settings to mess with. Just install, activate and you’re good to go.

Glutton for Punishment?

You can also achieve the same thing with no plugin too.

The trick to removing the category base is to go to Settings > Permalinks and set the following:

  1. Custom Structure to /%category%/%postname%/
  2. Category base to .

The Problem

Everything seems to work until you try to go to page two of your Category archives and it takes you to a 404 page not found error.

Now, that sucks. What’s happening here is that /page/2 is conflicting with the custom permalink structure.

How do I fix it?

First, when you investigate the request, you find that there is an additional key of ‘name’ in the query that is not present with a normal paged archive. So one method to go about this is to remove the offending key before WordPress tries to process the request.

You can do this by adding the following code to your functions.php of your theme:

function mytheme_request($query_string ) {
  if( isset( $query_string['page'] ) ) {
    if( !empty($query_string['page']) ) {
      if( isset( $query_string['name'] ) ) {
        unset( $query_string['name'] );
  return $query_string;
add_filter('request', 'mytheme_request');

Not quite there

When you test the code, you will find that you no longer get a 404 error. Great! But hold on, you will now notice that the paging takes you back to the first page over and over again.

What’s happening here is that the page number is not being provided to the WordPress query. So in the follow code snippet, we will take the page number from the path and set it in the WordPress query.

function mytheme_pre_get_posts( $query ) {
  if( $query->is_main_query() && !$query->is_feed() && !is_admin() ) {
    $query->set( 'paged', str_replace( '/', '', get_query_var( 'page' ) ) );

Again, add this code to your functions.php and then try it out.

Viola! You’re Now Set

Not impressed? Or just feeling lazy? I’m surprised you made it this far then. If you missed it, there is also a plugin available that helps you remove the category base with no fuss.

Drupal 7.14 Crashes Apache Server on a Windows Environment

I have experienced rare cases when visiting a particular URL where the Apache Server crashes on a fresh installation of Drupal 7.14 running WAMP on Windows XP or 7.

The common solution was to open the file causing the problem and re-save it. However, this did not explain why it was happening. Fortunately, I was able to consistently reproduce this problem when I installed the Internationalization module and visited admin/config/regional/language which would result in Apache crashing.

This information finally lead me to

What I learned was it is actually a PHP 5.3.10 bug that triggers when processing include/require files with sizes that are exact multiples of 4096 bytes and causes PHP to segfault (!).

The reason why re-saving the files worked is because the line feeds in the file are re-formatted from \n (unix style) to \r\n (windows style) which changes the files size from the problematic value of 53248 (exactly 52 KB).

How to delete a remote tag in Git

My obsessive compulsive nature of having everything neat and tidy finally got the better of me and prompt me to delete some tags from a remote Git repository. Strangely, SourceTree and TortoiseGit do not provide an option for this in the GUI.

Thankfully, a quick trip to the command line helped solve the problem and it goes like this:

git tag -d name_of_tag
git push origin :refs/tags/name_of_tag

This should explicitly delete the tag name_of_tag on the remote repository.

How to enable libcurl in WAMP

Having developed mostly in a MAMP environment, I have taken many things for granted. Today, while working with WAMP, I was pleasantly surprised by a “Fatal error: Call to undefined function: curl_init()”.

It took a few extra steps to get cURL working. WAMP comes preinstalled with many extensions, including cURL, but for some reason many are not enabled by default and enabling php_curl from within the WAMP menu did not solve my problem.

How to enable libcurl in WAMP

  1. Find and open c:\wamp\bin\php\php5.2.6\php.ini
  2. Uncomment ;extension=php_curl.dll
  3. Do the same for c\:wamp\bin\apache\apache2.2.8\bin\php.ini
  4. Restart WAMP and happy coding.
Still not working? A good place to start is check if Apache is loading the extension. Open both php.ini and make sure extension_dir is pointing to c:\wamp\bin\php\php5.2.6\ext

Have a question or want to say hi?

Send me an email or find me on: