Search code examples
xsltfilemaker

Filemaker XSL Select Column By Name


I am looking to export from Filemaker using column names (instead of positions). Currently I export the following XSL stylesheet that exports by position with:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:fm="http://www.filemaker.com/fmpxmlresult" exclude-result-prefixes="fm" >
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
  <people>
    <xsl:for-each select="fm:FMPXMLRESULT/fm:RESULTSET/fm:ROW">
      <person>
        <name>
          <xsl:value-of select="fm:COL[01]/fm:DATA"/>
        </name>
        <location>
          <xsl:value-of select="fm:COL[02]/fm:DATA"/>
        </location>
      </person>
    </xsl:for-each> 
  </people>
</xsl:template>
</xsl:stylesheet>

Any ideas? Thanks.


Solution

  • If you just want to make the code more readable, then I'd suggest something simple, like:

    <!-- expected columns -->
    <xsl:variable name="NAME" value="1" />
    <xsl:variable name="LOCATION" value="2" />
    <!-- ... -->
    <people>
      <xsl:for-each select="fm:FMPXMLRESULT/fm:RESULTSET/fm:ROW">
        <person>
          <name>
            <xsl:value-of select="fm:COL[$NAME]/fm:DATA"/>
          </name>
          <location>
            <xsl:value-of select="fm:COL[$LOCATION]/fm:DATA"/>
          </location>
        </person>
      </xsl:for-each> 
    </people>
    

    BTW, with <xsl:value-of /> you can omit the fm:DATA, i.e. use:

    <xsl:value-of select="fm:COL[$LOCATION] />
    

    It will return the same result.

    If you need something more sophisticated, please explain.

    Update:

    To refer to columns by column names is harder, but possible with something like that:

    <!-- Define a key to get a field and all fields that precede it by the field name -->
    <xsl:key name="N" match="/fm:FMPXMLRESULT/fm:METADATA/fm:FIELD" use="@NAME" />
    <xsl:key name="N" match="/fm:FMPXMLRESULT/fm:METADATA/fm:FIELD" 
      use="following-sibling::fm:FIELD/@NAME" />
    <!-- Then *count* them it in the code like that -->
    <people>
      <xsl:for-each select="fm:FMPXMLRESULT/fm:RESULTSET/fm:ROW">
        <person>
          <name>
            <xsl:value-of select="fm:COL[count(key('N', 'name'))]" />
          </name>
          <location>
            <xsl:value-of select="fm:COL[count(key('N', 'location'))]" />
          </location>
        </person>
      </xsl:for-each> 
    </people>
    

    Not utterly elegant, but works.