WIP, psts in place, parsing mostly correclty

This commit is contained in:
2020-09-21 21:56:11 -05:00
parent 8de94aa769
commit d274352b5f
87 changed files with 4820 additions and 11 deletions

View File

@@ -0,0 +1,168 @@
---
layout: post
title: "Grouping into Rows with XSLT"
date: 2012-03-05
description: "Grouping into Rows with XSLT"
categories: [programming]
tags: [xslt]
---
Lets say you have a simple XML document that looks something like this:
{% highlight xml %}
<root>
<Pod id="1"></Pod>
<Pod id="2"></Pod>
<Pod id="3"></Pod>
<Pod id="4"></Pod>
</root>
{% endhighlight %}
The content or meaning of the pods is irrelevant. The idea is that you have a “list” of elements (pods in this case) in your XML. How, then, do you use XSLT to group these pods into rows of two, three or whatever number of pods across? Something like this:
{% highlight xml %}
<div>
<div class="row">
<div class="pod"> pod 1 </div>
<div class="pod"> pod 2 </div>
<div class="pod"> pod 3 </div>
</div>
<div class="row">
<div class="pod"> pod 4 </div>
</div>
</div>
{% endhighlight %}
This example would required three pods per row. The example XSLT below will work for any number of pods per row with a simple edit (explained below).
My first thought was from a very normal programmers perspective. Id use some kind of looping (with xsl:for-each) and just start a new row for each x number of pods. So, I did it that way and it worked. It was pretty ugly XSLT, but I didnt really think there was a better way to do it. But then a colleague looked over my shoulder and chuckled. “I did it that way at first too”, he said, “but thats not the XSLT way to do it.” He gave me a little bit of a clue of how it really should be done then he left, leaving me determined to find the “XSLT way” of doing it!
Turns out, it really isnt difficult. You just have to think a little differently and start using xsl:template, xsl:call-template and xsl:apply-templates effectively along with their select and match attributes. So, take a look at this XSLT file:
{% highlight xml %}
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="html"
version="1.0"
omit-xml-declaration="yes"
indent="yes"
encoding="utf-8" />
<xsl:template match="/root">
<xsl:apply-templates select="Pod[position() mod 3 = 1]" />
</xsl:template>
<xsl:template name="PodRow"
match="Pod[position() mod 3 = 1]">
<div class="row">
<xsl:choose>
<xsl:call-template name="PodWrapper"/>
<xsl:apply-templates
select="following-sibling::Pod[position() &lt; 3]"/>
</xsl:choose>
</div>
</xsl:template>
<xsl:template name="PodWrapper"
match="Pod[position() mod 3 &gt; 1]">
<div class="pod">
<xsl:call-template name="PodContent"/>
</div>
</xsl:template>
<xsl:template name="PodContent">
<! whatever content your "pods" contain can be marked up here >
</xsl:template>
</xsl:stylesheet>
{% endhighlight %}
Heres whats going on: first, we call xsl:apply-templates on the first and then every third Pod using “Pod[position() mod 3 = 1]”. This will select the Pod at the start of every row: Pods 1 and 4. Notice that XSLT indexing starts at 1 and NOT 0. The PodRow template will match these selected Pods.
Inside the PodRow template we have the HTML for the row. Inside the row HTML, we explicitly call the PodWrapper template for the current Pod. We then call xsl:apply-templates on the following siblings of the current Pod, but only on the next two of them. This grabs the remaining Pods in the row. This xsl:apply-templates select will match the PodWrapper template which creates the HTML for a single Pod.
Easy as pie! To change the number of pods in a row, update all of the “position() mod 3″s by replacing 3 with however many pods you want in a row. Then also make sure to update the xsl:apply-templates select attribute inside PodRow to be “position() < n-1″ where n is the number of Pods in a row.
## Identifying the last cell of every row
I needed another feature from my XSLT though. I needed every last pod in each row to have a special CSS class. This meant determining which pod was the last one in each row whether the row was full or not. This made the XSLT significantly more complicated, but not overwhelmingly so.
I needed my HTML to look like this (notice the additional “last” class):
{% highlight xml %}
<div>
<div class="row">
<div class="pod"> pod 1 </div>
<div class="pod"> pod 2 </div>
<div class="pod last"> pod 3 </div>
</div>
<div class="row">
<div class="pod last"> pod 4 </div>
</div>
</div>
{% endhighlight %}
So, this is what I had to do:
{% highlight xml %}
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="html"
version="1.0"
omit-xml-declaration="yes"
indent="yes"
encoding="utf-8" />
<xsl:template match="/root">
<xsl:apply-templates select="Pod[position() mod 3 = 1]" />
</xsl:template>
<xsl:template name="PodRow"
match="Pod[position() mod 3 = 1]"
priority="2">
<div class="row">
<xsl:choose>
<xsl:when test="count(following-sibling::Pod) = 0">
<xsl:call-template name="PodWrapperLast"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="PodWrapper"/>
<xsl:apply-templates
select="following-sibling::Pod[position() &lt; 3]"/>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template name="PodWrapper"
match="Pod[position() mod 3 &gt; 1]"
priority="0">
<div class="pod">
<xsl:call-template name="PodContent"/>
</div>
</xsl:template>
<xsl:template name="PodWrapperLast"
priority="1"
match="Pod[position() mod 3 = 0 or position() = last()]">
<div class="pod last">
<xsl:call-template name="PodContent"/>
</div>
</xsl:template>
<xsl:template name="PodContent">
<! whatever content your "pods" contain can be marked up here >
</xsl:template>
</xsl:stylesheet>
{% endhighlight %}
This version of the XSLT functions exactly the same as the previous one. The only additions are for identifying the last pod in each row for all cases. So, here is what has changed.
The xsl:apply-templates call inside of PodRow now matches one of two templates: PodWrapper or PodWrapperLast. You guessed it, PodWrapperLast just has an extra “last” class on the Pod div and a fancy match attribute. “Pod[position() mod 3 = 0 or position() = last()]” will match Pod numbers 3, 6, etc (in other words, the last Pod of every row) or the last Pod in the XML (no matter what number it is).
Notice the new xsl:choose inside of our PodRow template. This handles the case where the last Pod in the XML is also the first Pod in a row.
Notice also the “priority” attributes on the templates now. This prevents the PodWrapperLast template from matching the first Pod in a row if that first Pod is also the last Pod in the XML.

View File

@@ -0,0 +1,10 @@
---
layout: post
title: "Easy Way to Make Huge Maps with Google Maps"
date: 2012-03-07
description: "Easy Way to Make Huge Maps with Google Maps"
categories: [programming]
tags: [google-maps]
---
[Easy way to make huge maps with Google Maps](http://www.metacafe.com/watch/1073912/google_maps_hack_how_to_save_large_maps/)

View File

@@ -0,0 +1,69 @@
---
layout: post
title: "Change the color of an icon with Gimp"
date: 2012-03-15
description: "Change the color of an icon with Gimp"
categories: [programming]
tags: [gimp]
---
Fairly often, I run across the perfect icon that I need for a website, but its just the wrong color. I want to keep the nice blending to the background of the icon around the edges, the shape and everything that makes the icon look spiffy. I just want the main color to be something else.
It took me a long time to figure out a good method (Im no graphic designer!), but I eventually came a cross a really easy method that works well using trusty Gimp. Ill walk you through it.
## 1. Find an Icon
The first step, of course, is to find an icon. There are billions of free ones out there on the web. This is mine.
![Blue phone icon](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/icon-phone-blue.png)
I love it. Its just what I needbut what a terrible color! I need something else. Its a PNG and when I open it in Gimp, heres what it looks like.
![Original in Gimp](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/original_in_gimp-300x236.png)
You can see the edges have been blended into a white background which would work great if I only ever put it on a white background. Well, I just might be doing that, but Im too much of a perfectionist to use it like that. So, lets get to work.
## 2. Create a color layer
Add a new layer to the image by selecting Layer > New Layer. Call it “color”. Make sure its on top of the “Background” layer.
![Adding a color layer](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/color_layer-149x300.png)
Fill this new layer with the color you want to change the icon to. Im using this lovely puke color (not my choice!): #afbd0a.
Now, hide this new layer so we can work on the “Background” layer by clicking on the eye button just to the left of the layer thumbnail.
## 3. Manipulate the icon colors
Select the “Background” layer. Desaturate the image by selecting Colors > Desaturate. I choose “Lightness” from the dialog box that pops up.
Now, invert the image by selecting Colors > Invert. Next, create another layer called “mask” and fill it with black. Move this layer below the “Background” layer. Your layers should look like the image below.
![Creating the mask layer](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/mask_layer-209x300.png)
Right-click on the “Background” layer and select “Merge down”. Now you should have something similar to the image below.
![After merging down](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/after_merge_down-300x156.png)
## 4. Adjust the curves
Now, with the “mask” layer selected, select Colors > Curves. In the dialog, drag the very middle of the line straight up to the top-center of the graph. Gimp should look like the screenshot below. Click “OK”.
![Adjusting the curves](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/curves-300x189.png)
## 5. Create a layer mask on the “color” layer
Now, with the “mask” layer selected, copy the entire layer by selecting Select > All. Then select Edit > Copy.
Next, right-click on the “color” layer and select “Add layer mask”. Choose “Black (full transparency)” and make sure “Invert mask” is checked.
Paste what youve copied to the layer mask by selecting Edit > Paste. Youll notice a new layer called “Floating selection (Pasted layer)”. Right-click on this new layer and select “Anchor layer”. The pasted layer will now be merged with your anchor layer.
## 6. Youre done!
Now hide your “mask” layer and show your “color” layer. Perfect!
![Completed image](/assets/images/2012-03-15-change-the-color-of-an-icon-with-gimp/done-300x163.png)
You now have a new icon with a completely different color, but with the nice blending at the edges and perfect shape of the original icon. Dont believe me? Well, test it! Select your “mask” layer and delete everything on it. Fill it with any background color you want and see how it looks. Make sure to show your “mask” layer again by click on the eye button.
Hope this was helpful! You can apply your layer mask on the “color” layer if you want. But, I like to keep it as it is and save the file as an xcf for later use. This way, if you ever need the icon in another color, all you have to do is change the fill color of the “color” layer and youre done.