The EESchema default XSL processor is xsltproc. I have dealt with libxml in the past, and I found it really hard to work with on Windows. Based on Dolganoff’s posting “BOM generation in “new” Kicad (Windows)”, I installed saxon9he on my PC instead of xsltproc. However, when I downloaded the latest version, there was only a saxon9he.jar file. No problem, since I already had Java installed on my PC. Based on installing Saxon in the obvious location, the command line becomes:
java -jar c:\saxon\saxon9he.jar -t “%I” -xsl:“C:\Program Files\KiCad\bin\scripting\plugins\bom2csv.xsl” -o:"%O.csv"
Saxon9he has worked flawlessly for me, generating both BOM’s and netlists. However the output is not sorted, so it’s difficult to work with. Using the standard XLS version 1.0 sorting function to sort components by reference is also unsatisfactory, since it is only possible to order components alphabetically, so that they are still not in proper order (e.g. J18, J19, J2, J20…). Maybe there is another way, but XSL version 2.0 added regular expression matching, which will work just fine to sort references properly. Saxon9he is fully XSL version 2.0 compliant.
Rather than tackle regular expressions directly, I downloaded the functx library from “http://www.xsltfunctions.com/xsl/download.html”. I stored the “functx-1.0-doc-2007-01.xsl” file in the same directory as bom2csv.xsl, then I made the obvious changes to bom2csv.xsl to import the functx library and sort the components. A copy of my modified bom2csv.xsl file appears below.
Note that you will need Administrator privilege on Windows to install Saxon in a privileged location such as c:\saxon. You will need Administrator privilege to replace bom2csv.xsl or to modify it in situ. (I used Notepad++ and ran it with Administrator privilege.) You’ll also need Administrator privilege to copy the functx library to that same directory. The approved approach would be to put those files in some subdirectory off of your user directory. (Modify the above EESchema command line accordingly.)
Without having tested, I can’t say if the following script will work with xsltproc. However since saxon9he is available in Java, it should be possible to run the script with saxon9he on both Linux and OS X.
<!--XSL style sheet to convert EESCHEMA XML Partlist Format to CSV BOM Format
Based on bom2csv.xsl, which is:
Copyright (C) 2013, Stefan Helmert.
GPL v2.
Functionality:
Generate csv table with table head of all existing field names
and assigned field values entries.
How to use this is explained in eeschema.pdf chapter 14. You enter a command line into the
BOM exporter using a new (custom) tab in the BOM export dialog. The command is
similar to
on Windows:
xsltproc -o "%O.csv" "C:\Program Files (x86)\KiCad\bin\plugins\bom2csv.xsl" "%I"
on Linux:
xsltproc -o "%O.csv" /usr/local/lib/kicad/plugins/bom2csv.xsl "%I"
Instead of "%O.csv" you can alternatively use "%O" if you will supply your own file extension when
prompted in the UI. The double quotes are there to account for the possibility of space(s)
in the filename.
-->
<!--
@package
Generate a BOM as a comma separated list (csv file type).
One component per line
Fields are
Reference, Symbol, Value, Footprint, Datasheet, [additional defined fields...]
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "
"> <!--new line: remove 
 for linux or os-x -->
]>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:functx="http://www.functx.com">
<xsl:import href="functx-1.0-doc-2007-01.xsl"/>
<xsl:output method="text"/>
<!-- for table head and empty table fields-->
<xsl:key name="headentr" match="field" use="@name"/>
<!-- main part -->
<xsl:template match="/export">
<xsl:text>Reference, Symbol, Value, Footprint, Datasheet</xsl:text>
<!-- find all existing table head entries and list each one once -->
<xsl:for-each select="components/comp/fields/field[generate-id(.) = generate-id(key('headentr',@name)[1])]">
<xsl:text>, </xsl:text>
<xsl:value-of select="@name"/>
</xsl:for-each>
<xsl:text>&nl;</xsl:text>
<!-- all table entries -->
<xsl:apply-templates select="components/comp">
<xsl:sort select="functx:substring-before-match(@ref,'[0-9]')"/>
<xsl:sort select="functx:substring-after-last-match(@ref,'[a-zA-Z]')" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<!-- the table entries -->
<xsl:template match="components/comp">
<xsl:value-of select="@ref"/><xsl:text>,</xsl:text>
<xsl:value-of select="libsource/@lib"/><xsl:text>:</xsl:text><xsl:value-of select="libsource/@part"/><xsl:text>,</xsl:text>
<xsl:value-of select="value"/><xsl:text>,</xsl:text>
<xsl:value-of select="footprint"/><xsl:text>,</xsl:text>
<xsl:value-of select="datasheet"/>
<xsl:apply-templates select="fields"/>
<xsl:text>&nl;</xsl:text>
</xsl:template>
<!-- table entries with dynamic table head -->
<xsl:template match="fields">
<!-- remember current fields section -->
<xsl:variable name="fieldvar" select="field"/>
<!-- for all existing head entries -->
<xsl:for-each select="/export/components/comp/fields/field[generate-id(.) = generate-id(key('headentr',@name)[1])]">
<xsl:variable name="allnames" select="@name"/>
<xsl:text>,</xsl:text>
<!-- for all field entries in the remembered fields section -->
<xsl:for-each select="$fieldvar">
<!-- only if this field entry exists in this fields section -->
<xsl:if test="@name=$allnames">
<!-- content of the field -->
<xsl:value-of select="."/>
</xsl:if>
<!--
If it does not exist, use an empty cell in output for this row.
Every non-blank entry is assigned to its proper column.
-->
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>