Thursday 6 December 2007

How to Enable Root on a Mac running Leopard

1 - Go to applications->utilities

2 - Open Directory Utility

3 - Unlock it if not already unlocked

4 - Go to Edit->Enable Root User

5 - Enter a password for root

Now, you can su to root in terminal sessions, and the 'Other Users' option will show up on the login window.

Monday 26 November 2007

JAXB ClassCastException

JAXB marshalling and unmarshalling throws runtime/classcast exception

If you search the web, you will encounter lots of discussions about what causes a class cast exception in JAXB when you try and implement the NamespacePrefixMapper and then call marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", ... ).

However, the simplest cases are not always discussed.

We encountered this problem with marshalling xml in an EJB3 environment and it turned out to be a genuine class cast exception as follows:

Code was being called from a servlet. However, the Web Server was using JAX-WS which was using a different version of JAXB to the back-end. (sharing the libraries during deployment).

The solution (quick hack for us) was to get the Servlet to call a session bean which was using the correct version of JAXB. Obviously at some point we should ensure consistency across the board, but for anyone who is getting a ClassCastException when using NamespacePrefixMapper - check the jars first ;)

Using Xalan with XMLSpy

So simple it's painful ;)

1 - Download xalan.jar
2 - set your CLASSPATH to include xalan.jar
3 - Select tools->options->XSL in XmlSpy
4 - check 'External xsl transformation program'
5 - enter the line: java org.apache.xalan.xslt.Process -in %1 -xsl %3 -out %2

Done!!

Wednesday 14 November 2007

Using Time Machine to Back up onto a NAS Server

It is easy to add NAS Devices as backup Devices for Timemachine:

Start the terminal app on the mac where You want to use Timemachine
Enter the following in Terminal: defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

After that You will see all possible networkshares in Timemachine (and You can also use them).

Monday 5 November 2007

Sorting with XSLT

Here’s a challenge, I have an xml file structure as follows:


<?xml version="1.0" encoding="UTF-8"?>
<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <person>
              <height>1.81</height>
              <dob>1990-01-17</dob>
       </person>
       <person>
              <height>1.51</height>
              <dob>1981-09-10</dob>
       </person>
       <person>
              <height>1.31</height>
              <dob>1990-02-07</dob>
       </person>
       <person>
              <height>1.71</height>
              <dob>1981-09-20</dob>
       </person>             
</people>


I want to create an xml file (averageHeight.xml) that sorts the people into average height by month within year.
e.g


<average_height>
       <year no=”1981”>
              <month no=”09”>
                     <height>1.61</height>
              </month>
       </year>
       ….


Let’s break the problem down into manageable chunks.
Here’s a simple transform that extracts the dob of each person


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:element name="average_height">
                     <xsl:apply-templates select="//person"/>
              </xsl:element>
       </xsl:template>
       <xsl:template match="person">
              <xsl:element name="year">
                     <xsl:value-of select="dob"/>
              </xsl:element>
       </xsl:template>
</xsl:stylesheet>


This gives:


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year>1990-01-17</year>
       <year>1980-11-10</year>
       <year>1990-02-07</year>
       <year>1981-09-20</year>
</average_height>


Now we want to write it to averageHeight.xml, so let’s add the <xsl:result-document href=" averageHeight.xml">
To give:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="//person"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="person">
              <xsl:element name="year">
                     <xsl:value-of select="dob"/>
              </xsl:element>
       </xsl:template>
</xsl:stylesheet>


This now gives averageHeight.xml with the following content


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year>1990-01-17</year>
       <year>1980-11-10</year>
       <year>1990-02-07</year>
       <year>1981-09-20</year>
</average_height>


Now, let’s extract and sort the year: but first we need to change the xslt to use a for-each so we can sort:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:for-each select="person">
                     <xsl:element name="year">
                            <xsl:value-of select="substring(dob,1,4)"/>
                     </xsl:element>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives:


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year>1990</year>
       <year>1980</year>
       <year>1990</year>
       <year>1981</year>
</average_height>


Now, let’s sort it:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:for-each select="person">
                     <xsl:sort select="substring(dob,1,4)"/>
                     <xsl:element name="year">
                            <xsl:value-of select="substring(dob,1,4)"/>
                     </xsl:element>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


to give:


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year>1980</year>
       <year>1981</year>
       <year>1990</year>
       <year>1990</year>
</average_height>


Now let’s eliminate duplicates:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:element name="year">
                            <xsl:value-of select="."/>
                     </xsl:element>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year>1980</year>
       <year>1981</year>
       <year>1990</year>
</average_height>


now, let’s add in the months:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:element name="year">
                            <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                            <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                   <xsl:element name="month">
                                          <xsl:value-of select="substring(dob,6,2)"/>
                                   </xsl:element>
                            </xsl:for-each>
                     </xsl:element>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1980">
              <month>11</month>
       </year>
       <year no="1981">
              <month>09</month>
       </year>
       <year no="1990">
              <month>01</month>
              <month>02</month>
       </year>
</average_height>


I want to introduce a duplicate month to test the removal of duplicate months. So let's change our original xml to this:


<?xml version="1.0" encoding="UTF-8"?>
<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <person>
              <height>1.81</height>
              <dob>1990-01-17</dob>
       </person>
       <person>
              <height>1.51</height>
              <dob>1981-09-10</dob>
       </person>
       <person>
              <height>1.31</height>
              <dob>1990-02-07</dob>
       </person>
       <person>
              <height>1.71</height>
              <dob>1981-09-20</dob>
       </person>             
</people>


and transform it with:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:element name="year">
                            <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                            <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                   <xsl:element name="month">
                                          <xsl:value-of select="substring(dob,6,2)"/>
                                   </xsl:element>
                            </xsl:for-each>
                     </xsl:element>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives:


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month>09</month>
              <month>09</month>
       </year>
       <year no="1990">
              <month>01</month>
              <month>02</month>
       </year>
</average_height>


now, let’s remove duplicate months: - part 1 – create the variable:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                     <xsl:element name="year">
                            <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                            <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                   <xsl:element name="month">
                                          <xsl:value-of select="substring(dob,6,2)"/>
                                   </xsl:element>
                            </xsl:for-each>
                     </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="$months-in-years/year">
                            <xsl:copy-of select="."/>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month>09</month>
              <month>09</month>
       </year>
       <year no="1990">
              <month>01</month>
              <month>02</month>
       </year>
</average_height>


now, remove the duplicates:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                   <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                          <xsl:element name="month">
                                                 <xsl:value-of select="substring(dob,6,2)"/>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="$months-in-years/year">
                            <xsl:sort select="."/>
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="@no"/></xsl:attribute>
                                   <xsl:for-each select="month[not(.=preceding::month)]">
                                          <xsl:sort select="."/>
                                          <xsl:element name="month">
                                                 <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month no="09"/>
       </year>
       <year no="1990">
              <month no="01"/>
              <month no="02"/>
       </year>
</average_height>


now, let’s add the dob’s as an interim measure


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                   <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                          <xsl:element name="month">
                                                 <xsl:value-of select="substring(dob,6,2)"/>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="$months-in-years/year">
                            <xsl:sort select="."/>
                            <xsl:element name="year">
                                   <xsl:variable name="year" select="@no"/>
                                   <xsl:attribute name="no"><xsl:value-of select="@no"/></xsl:attribute>
                                   <xsl:for-each select="month[not(.=preceding::month)]">
                                          <xsl:sort select="."/>
                                          <xsl:variable name="month" select="."/>
                                          <xsl:element name="month">
                                                 <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                                 <xsl:for-each select="$people/person[substring(dob,1,4)=$year and substring(dob,6,2)=$month]">
                                                        <xsl:element name="dob">
                                                               <xsl:value-of select="dob"/>
                                                        </xsl:element>
                                                 </xsl:for-each>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


to give:


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month no="09">
                     <dob>1981-09-10</dob>
                     <dob>1981-09-20</dob>
              </month>
       </year>
       <year no="1990">
              <month no="01">
                     <dob>1990-01-17</dob>
              </month>
              <month no="02">
                     <dob>1990-02-07</dob>
              </month>
       </year>
</average_height>


now, let’s change that dob to height:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                   <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                          <xsl:element name="month">
                                                 <xsl:value-of select="substring(dob,6,2)"/>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="$months-in-years/year">
                            <xsl:sort select="."/>
                            <xsl:element name="year">
                                   <xsl:variable name="year" select="@no"/>
                                   <xsl:attribute name="no"><xsl:value-of select="@no"/></xsl:attribute>
                                   <xsl:for-each select="month[not(.=preceding::month)]">
                                          <xsl:sort select="."/>
                                          <xsl:variable name="month" select="."/>
                                          <xsl:element name="month">
                                                 <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                                 <xsl:for-each select="$people/person[substring(dob,1,4)=$year and substring(dob,6,2)=$month]">
                                                        <xsl:element name="height">
                                                               <xsl:value-of select="height"/>
                                                        </xsl:element>
                                                 </xsl:for-each>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month no="09">
                     <height>1.51</height>
                     <height>1.71</height>
              </month>
       </year>
       <year no="1990">
              <month no="01">
                     <height>1.81</height>
              </month>
              <month no="02">
                     <height>1.31</height>
              </month>
       </year>
</average_height>


now let’s average the heights


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="$years/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                   <xsl:for-each select="$people/person[substring(dob,1,4)=$year]">
                                          <xsl:element name="month">
                                                 <xsl:value-of select="substring(dob,6,2)"/>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="$months-in-years/year">
                            <xsl:sort select="."/>
                            <xsl:element name="year">
                                   <xsl:variable name="year" select="@no"/>
                                   <xsl:attribute name="no"><xsl:value-of select="@no"/></xsl:attribute>
                                   <xsl:for-each select="month[not(.=preceding::month)]">
                                          <xsl:sort select="."/>
                                          <xsl:variable name="month" select="."/>
                                          <xsl:element name="month">
                                                 <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                                 <xsl:element name="height">
                                                        <xsl:value-of select="avg($people/person[substring(dob,1,4)=$year and substring(dob,6,2)=$month]/height)"/>
                                                 </xsl:element>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


gives


<?xml version="1.0" encoding="UTF-8"?>
<average_height>
       <year no="1981">
              <month no="09">
                     <height>1.61</height>
              </month>
       </year>
       <year no="1990">
              <month no="01">
                     <height>1.81</height>
              </month>
              <month no="02">
                     <height>1.31</height>
              </month>
       </year>
</average_height>


job done...

Actually, there's one problem that can arise with xalan parsers.

If you get the error message:

Can not convert #RTREEFRAG to a NodeList!

Then you need to include the xalan namespace as follows:


                   version="1.0"
                   xmlns:xalan="http://xml.apache.org/xalan"
                   exclude-result-prefixes="xalan">



and replace and references to variables that are node lists as follows:


<xsl:for-each select="$rtf/docelem//*">


becomes


<xsl:for-each select="xalan:nodeset($variablename)/docelem//*">


the final transform from our example, for use with a xalan parser becomes:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xalan="http://xml.apache.org/xalan" exclude-result-prefixes="xalan">
       <xsl:output method="xml"/>
       <xsl:template match="/">
              <xsl:result-document href=" averageHeight.xml">
                     <xsl:element name="average_height">
                            <xsl:apply-templates select="/people"/>
                     </xsl:element>
              </xsl:result-document>
       </xsl:template>
       <xsl:template match="people">
              <xsl:variable name="people" select="."/>
              <xsl:variable name="years">
                     <xsl:for-each select="person">
                            <xsl:sort select="substring(dob,1,4)"/>
                            <xsl:element name="year">
                                   <xsl:value-of select="substring(dob,1,4)"/>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:variable>
              <xsl:for-each select="xalan:nodeset($years)/year[not(.=preceding::year)]">
                     <xsl:variable name="year" select="."/>
                     <xsl:variable name="months-in-years">
                            <xsl:element name="year">
                                   <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                   <xsl:for-each select="xalan:nodeset($people)/person[substring(dob,1,4)=$year]">
                                          <xsl:element name="month">
                                                 <xsl:value-of select="substring(dob,6,2)"/>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:variable>
                     <xsl:for-each select="xalan:nodeset($months-in-years)/year">
                            <xsl:sort select="."/>
                            <xsl:element name="year">
                                   <xsl:variable name="year" select="@no"/>
                                   <xsl:attribute name="no"><xsl:value-of select="@no"/></xsl:attribute>
                                   <xsl:for-each select="month[not(.=preceding::month)]">
                                          <xsl:sort select="."/>
                                          <xsl:variable name="month" select="."/>
                                          <xsl:element name="month">
                                                 <xsl:attribute name="no"><xsl:value-of select="."/></xsl:attribute>
                                                 <xsl:element name="height">
                                                        <xsl:value-of select="avg($people/person[substring(dob,1,4)=$year and substring(dob,6,2)=$month]/height)"/>
                                                 </xsl:element>
                                          </xsl:element>
                                   </xsl:for-each>
                            </xsl:element>
                     </xsl:for-each>
              </xsl:for-each>
       </xsl:template>
</xsl:stylesheet>


now, the job's done!!

need to change: for example


<xsl:for-each select="xalan:nodeset($year)/year[not(.=preceding::year)]">


becomes:


<xsl:for-each select="xalan:distinct(xalan:nodeset($year)/year)">


reference: http://xml.apache.org/xalan-c/extensionslib.html

Saturday 3 November 2007

Moving to a Mac

Background



Having lived and breathed computers since 1980, I have been a long term customer of the Microsoft Track. Despite various roles in Unix Admin and development ranging from Minix thru Sco Unix to AIX, HPUX and now Linux, my home pcs have always been Microsoft boxes.


I develop in Java, C and C++ and so I have always wanted a powerful machine; and I travel a lot and so I have always wanted a laptop. By the time you’ve loaded Netbeans, Eclipse, JBOSS, Oracle or some other database, XML Spy and whatever else my current project deems to be important at the time; the machine and the operating system is taking quite a hit.


The Impetus to Move



More recently, when running all this on Vista I have found the machine just too unresponsive and so the decision had to be taken to change machines once again. My choices were simple (to me):


a Sony Vaio SZ5, 2.16 Intel Core 2 Duo with 2GB ram, or

a MacBook Pro, 2.4GHz Intel Core 2 Duo with 4GB ram.


Normally I would shy away from Mac because I have 15 years of files that are all windows files - documents, etc.


However, this time I found out about Parallels which allows Windows to be installed in parallel with Mac OS X.


Parallels, a demo of a 15” MacBook Pro and frustration at how long it was taking NetBeans to load finally did it for me.


The rest is the migration...



Useful Reading



As a first timer to Mac I decided to do a bit of reading beforehand. These two books were really useful and made the transition from Windows to Mac a breeze


- Switching to the Mac: The Missing Manual - Tiger Edition

- MAC OS X: The Missing Manual - Tiger Edition



Existing Setup



Before going on to the integration of my new Mac into my home, let’s take a look at my existing setup:


- BT Broadband internet along with all the problems that come with

using BT. (court action against BT already started)


- Wireless BT router acting as a DHCP server


- Wired ethernet LAN routed through the mains

- Solwise HomePlug Ethernet Adapter


- Thecus N5200 IP Storage Server currently using RAID 1 across two

750GB Seagate Hard Drives (space for another 3)

- Thecus N5200 External 5 Bay Hotswap NAS using SATA/SATAII + eSATA 4xUSB 2xGbE
- 750 Gb Seagate ST3750640AS-RK Barracuda 7200.10, SATA300, 7200 rpm, 16MB Cache, 8 ms, NCQ


- Sony Vaio A617S running Windows Vista Business, wired


- Sony Vaio TX2XP running Windows Vista Business, wireless


- Canon Pixma ip4300 inkjet printer connected to one of the USB ports

on the Thecus N5200


I won’t go into too much detail into the whys and wherefores for such a setup, suffice it to say that I can access all my files on the Thecus from whichever machine I am on, and whenever the BT Broadband fails, I don’t have all the hassle that Vista now gives me selecting (instead of auto connecting to) my wireless router.


Moving to the Mac



Okay, here goes. I’ve got my Mac and for now I am ignoring the wireless network and going with the wire network. So, cable into back of machine, power up and go with all the defaults until the machine is running.


The Mac has come complete with OS X 10.4 (Tiger) so the first few things I do are:


Configure Mac to require login

From the menu bar at the top, select:

- -> System Preferences...

- Security


check the following:

- Require password to wake this computer...

- Disable automatic login


Setup User Account Password

From the menu bar at the top, select:

- -> System Preferences...

- Accounts


Setup your accounts as you want them


Connect to the N5200



Double click the hard drive icon on the desktop

- Network -> My Group -> N5200 -> Connect


Select the required folder, click OK

Ignore the login/password options, but when prompted say OK to adding the entry to the KeyChain.


Connecting the Printer



From the menu bar at the top, select:

- -> System Preferences...

- Print and Fax


do the following:

- Click + to add printer

- Protocol: IPP

- Address: :631 - e.g. 192.168.1.64:631

- Queue: /printers/usb-printer

- Name: Home Printer, or whatever you choose

- Location: Living Room...

- Print Using: ...


When it comes to selecting the Printer Driver I found that the Canon printer drivers left me printing documents 1/4 size. I found that if you download the PrintFab drivers before you install your printer, you can use the appropriate PrintFab printer driver and they are much more reliable.



Installing Vista in Parallel



This is so easy, it is hardly worth mentioning. Insert the Parallels dvd and follow the instructions, installing all the defaults.


Then, insert your Vista dvd and Parallels will see it and take over the installation. Here’s the beauty; every time you are required to reboot Vista, it only reboots the Parallels window and not your whole machine. So you can still keep playing with your Mac.


If you want Vista to run inside it’s own Parallels window then leave everything as default.


If you want the Vista start button to be integrated with your Mac desktop then click the Coherence button (on the right hand pane of the Parallels window).


Repartitioning the Hard Drive



As always, I was so keen to play with my Mac that I got everything up and running and then my OS X 10.5 Leopard (beta) DVD arrived in the post from joining the Mac Developer Network.


Now, I have to resize my hard disk and a cursory glance at the Disk Utility tool would suggest that it can’t be done...


- but wait!


...


Open a Terminal Window

(look in the folder Applications -> Utilities -> Terminal)


...


At the command prompt type


computer name:~ login$ diskutil list


The computer will display a list of your hard disks and information about them.


Mine showed that my Tiger installation was on the whole disk as follows:


# type name size identifier

2: Apple HFS Macintosh HD 160GB disk0s2


...


This is the partition that I want to shrink so I can install Leopard. So first I determine the minimum and max size I can set the partition to using:


diskutil resizevolume disk0s2 limits


This gives me:


Current Size: 160GB

Min Size: 67GB

Max Size: 160GB


...


I am supposed to be able to resize the volume and create a new one at the same time but I managed to screw that up, so here is the command that I ran by accident :(


diskutil resizevolume disk0s2 80G


Now sit back and wait while the partition is verified and resized. Eventually you will be prompted to reboot the computer.


...


Reboot the computer from the Apple Icon in the top menu.


...


Now open the Disk Utility by selecting the icon:


Applications -> Utilities -> Disk Utility


...


Once in the Disk Utility, the disk will appear as disk0s3 but you cannot access it because it is not mounted.


Click on the Erase tab.


Set the following:


- Volume Format: Mac OS Extended (Journaled)

- Name: Leopard


Click the erase button


...


Now the volume appears on the computer.



Installing Leopard



Insert the Leopard dvd and click Install Max OS X


The computer will prompt you to restart the computer and also to enter your password to enable the installation.


Enter the password and click ok.


...


Follow the defaults.


When you are prompted to choose the installation location for Leopard, click on the Leopard drive and click.


Follow the defaults.


Backing up Mail



Backing up Mail is a simple case of copying files and folders:


Once you have created a backup folder the files/folders you need to backup are:


- from the Users -> username -> Library folder:


- Mail (folder)

- MailDownloads (folder)

- Application Support -> AddressBook (folder)

- Preferences -> com.apple.mail.plist (file)