Developer42

2010-06-29

My First Python Plugin

Filed under: Technology, WordPress — Tags: , , , , , , , , — Developer42 @ 22:51

I’ve read a lot about Python in the past, but have been so inundated with things to learn recently that it had always fallen to the bottom of the pile. However, recently I requested a feature for my favourite text editor, Programmers’ Notepad, and heard back from its developer, Simon, within moments of submitting my request. He’d provided a solution and instructions on how to implement it, which introduced me to a powerful set of features I’d previously been unaware of (namely that you could run apps which output to the command line straight from the tools menu, and have their output returned into the current document). After realising I’d been missing out on some of this potential, I spent a bit of time going over the pnotepad.org site, seeing what else I’d missed. This is where I come back to Python. PNotepad allows you to write custom scripts in Python, put them into pn’s \scripts directory, and run them from the scripts toolbar the next time you start up the editor. I figured any time spent learning python would easily be offset by the hours saved by having scripts take care of laborious tasks for me, so promptly downloaded and installed Python and PyPN (which enables Python scripts in PN), had a look at a script from the script repository, and a browse through the python manual, and then wrote my first script in a few minutes. For anyone wanting to see it, my script is a simple tool for replacing < > and & characters with their HTML codes, and inserting the PRE and CODE tags required to publish code to wordpress. I’ve uploaded it to the script share, here.

First Impressions
My first impressions of Python, after having coded for all of 20 mins or so, are that it’s a really simple language to learn, which anyone (including non developers) should be able to pick up pretty quickly. There are a few bits I’m not so keen on; select statements don’t exist, using instead piles of else-if (elif) statements, and not having curly brackets and semi-colons, but instead relying on indentation leaves me feeling a little out of my comfort zone, but all this is just a familiarity thing, which I’m sure I’ll soon get over. I’m hoping to write a few more scripts over the next few weeks (assuming I can find interesting and required things to write), and to learn a bit more about Python outside of PN, after which I’ll report back on my experiences for anyone else interested in heading in that direction.

Steps Taken to Run Python in PN
If you’d also like to get into Python for PN, here’s a step by step set of instructions on what to do (skipping a few steps to avoid typing “click next” too many times).
Download & install/extract the following, in the order listed below:

Once installed, go to the command line (windows key + r, cmd, enter), navigate to the programmer’s notepad directory (cd %programfiles%\programmer*), then type the following “pn –findexts”. It looks like nothing’s happened, but that’s good; it hasn’t errorred.
Next, load up programmer’s notepad, click view, windows, scripts (or press alt+F10), and you should see a list of available scripts.
Get an existing script from the script share site: http://scriptshare.rocketmonkeys.com/ and save the file to your …\Programmer’s Notepad\scripts\ directory.
Close and reopen PN. You should now see a new script (or several) listed in the scripts toolbar.
From here on, it’s pretty easy to figure out what to do to create your own scripts by looking at existing scripts and python code, and playing.
Good luck.

Grouping Items using XSLT

Filed under: Technology — Tags: , , , , , , — Developer42 @ 12:16

Another XSLT problem. How do you group items together using XSLT, when the sort function isn’t available (e.g. the Muenchian Method won’t work).

The XSLT

<xsl:stylesheet version="2.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:output method="xml" indent="yes" encoding="utf-8" /> <!-- keeping utf 8 rather than 16 as this will be big -->
  <xsl:strip-space elements="*"/>

  <!-- ROOT -->
  <xsl:template match="/node()">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:for-each select="./node()[not(journalName = preceding-sibling::Row/journalName)]/node()[local-name()=&quot;journalName&quot;]"><!-- for each distinct JournalName -->
        <xsl:variable name="journalName"><xsl:value-of select="."/></xsl:variable>
        <Journal>
          <xsl:copy-of select="."/>
          <xsl:apply-templates select="//node()[local-name()=&quot;Row&quot; and journalName=$journalName]" />
        </Journal>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <!-- By default, copy everything as is -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <!-- but as we already have the journal name, strip it -->
  <xsl:template match="node()[local-name()=&quot;journalName&quot;]" />
  
  <!-- and demo that we could manipulate other elements if needed -->
  <xsl:template match="node()[local-name()=&quot;otherData&quot;]">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:attribute name="newAttribute">Demo</xsl:attribute>
      <xsl:value-of select="."/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

Sample Data

<Root>
  <Row>
    <journalName>a</journalName>
	<otherData>hello1</otherData>
	<other>hellox1</other>
  </Row>
  <Row>
    <journalName>a</journalName>
	<otherData>hello2</otherData>
	<other>hellox2</other>
  </Row>
  <Row>
    <journalName>b</journalName>
	<otherData>hello3</otherData>
	<other>hellox3</other>
  </Row>
  <Row>
    <journalName>b</journalName>
	<otherData>hello4</otherData>
	<other>hellox4</other>
  </Row>
  <Row>
    <journalName>a</journalName>
	<otherData>hello5</otherData>
	<other>hellox5</other>
  </Row>
</Root>

2010-06-24

Getting Todays Date from an XSLT Transform

Filed under: Microsoft, Technology — Developer42 @ 17:38

Today I hit an issue whereby I needed to put the current date into an XML document, but found that the current-datetime() function wasn’t supported by my xsl processor. As a result, I’ve written the below code to get around the issue (heavily based on resources found elsewhere on the web). Please see the comments inline for information on what each bit’s doing.
One extra point is that this will only work if scripts are available to your XSLT processor. If you’re using C#, please lookup XsltSettings.EnableScripts for more info.


<xsl:stylesheet version="2.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:jsGoodies="urn:internal:jsGoodies">
  <!-- nb: the msxsl and jsGoodies namespaces above are required for the date function.  The ms one allows me to use scripts, the jsgoodies references my script, below -->
  <!-- dont indent; improves processing speed - but leave as yes for debugging - also strip all whitespace if not debugging, as this will help speed and file size -->
  <xsl:output method="xml" indent="yes" encoding="utf-16" />
  <!-- <xsl:strip-space elements="*" /> -->
< put the functions result into a variable to save reprocessing each time its referenced >
  <xsl:variable name="now" select="jsGoodies:GetCurrentDateTime()" />
  <xsl:template match="/node()">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
          <xsl:element name="Now">
        <!-- use xsl:element instead of just &lt;Now&gt; to avoid getting namespace fluff -->
          <xsl:value-of select="$now"/>
          </xsl:element>
      <xsl:apply-templates select="*"/>
    </xsl:copy>
  </xsl:template>

  <!-- By default, copy everything as is -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

    <!-- 
    current-date() is not available in the current MS version of XSLT.  Therefore using a JScript hack
    http://social.msdn.microsoft.com/Forums/en-US/sqlintegrationservices/thread/d8c0b688-e176-4316-b70a-637e2bfcf6dc/ 
    -->  
    <msxsl:script language="JScript" implements-prefix="jsGoodies">
      <![CDATA[
        //cdata tells xml parser to ignore this bit, allowing me to do things like this "i > u" & that <--.  Very useful when writing code 🙂
        function GetCurrentDateTime()
        {
         var result = new Date(); 
         return ToXmlDate(result);
        }
        function ToXmlDate(d)
        {
          //I'm using the UTC date to avoid timezone issues
          return d.getUTCFullYear()
          + '-' + ToMonth(d.getUTCMonth())
          + '-' + LPad(d.getUTCDate(),'0',2)
          + 'T' + LPad(d.getUTCHours(),'0',2)
          + ':' + LPad(d.getUTCMinutes(),'0',2)
          + ':' + LPad(d.getUTCSeconds(),'0',2)
          + '.' + LPad(d.getUTCMilliseconds(),'0',3)
          + 'Z';
        }
        function ToMonth(i)
        {
          i++; //the month is given as a zero based index, rather than the month value
          return LPad(i,'0',2);
        }
        function LPad(s,c,l)
        {
          return (""+s).PadLeft(l,c); //ensures that s is a string, then uses the strings padleft function
        }
    ]]>
    </msxsl:script>

</xsl:stylesheet>   

Blog at WordPress.com.

%d bloggers like this: