I have a problem with processing following xml code:
<?xml version="1.0" encoding="UTF-8"?>
<searchresult>
<head>
<heading>
<title>Column1</title>
<dataType>TEXT</dataType>
</heading>
<heading>
<title>Column2</title>
<dataType>DATE</dataType>
<dataFormat>SHORT_DATE</dataFormat>
</heading>
</head>
<data>
<row>
<column>
<value>Hello</value>
<column>
<column>
<value>2012-07-12</value>
<column>
</row>
<row>
<column>
<value>Good bye</value>
<column>
<column>
<value>2012-07-13</value>
<column>
</row>
</data>
</searchresult>
I need to transform this xml to EXCEL compatible file (I use urn:schemas-microsoft-com:office:office, urn:schemas-microsoft-com:office:excel and urn:schemas-microsoft-com:office:spreadsheet namespaces for it)
Problem is that I don't know how to apply information from head/heading elements dataType + dataFormat (if available) on row/column/value. This will help Excel to recognize which datatype is inside its cells. It is obvious that i need to preserve order so. Number of columns and its metadata is dynamic and each XML may differ.
I need to get something like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Workbook --several namespaces here-->
<Worksheet ss:Name="SearchResult">
<Table x:FullRows="1" x:FullColumns="1">
<Row ss:Height="12.75">
<Cell>
<Data ss:Type="String">Column1</Data>
</Cell>
<Cell>
<Data ss:Type="String">Column2</Data>
</Cell>
</Row>
<Row ss:Height="12.75">
<Cell>
<Data ss:Type="String">Hello : TEXT</Data>
</Cell>
<Cell>
<Data ss:Type="Date">2012-07-12 : DATE - SHORT_DATE</Data>
</Cell>
</Row>
<Row ss:Height="12.75">
<Cell>
<Data ss:Type="String">Good bye : TEXT</Data>
</Cell>
<Cell>
<Data ss:Type="Date">2012-07-12 : DATE - SHORT_DATE</Data>
</Cell>
</Row>
</Table>
</Worksheet>
</Workbook>
I tried a few times create something useful and working but all my attempts fail. Current version is here:
<xsl:template match="searchresult">
<Worksheet>
--some unimportant script--
<Table x:FullColumns="1" x:FullRows="1">
<xsl:apply-templates select="head" />
<xsl:apply-templates select="elements/row"/>
</Table>
</Worksheet>
</xsl:template>
<xsl:template match="head">
<Row>
<xsl:for-each select="*">
<!-- resolve data-type and remember it as variable -->
<xsl:variable name="concat('dataType', position())" select="dataType">
<xsl:choose>
<xsl:when test="TEXT">
<xsl:value-of select=".">String</xsl:value-of>
</xsl:when>
<xsl:when test="DATE">
<xsl:value-of select=".">DateTime</xsl:value-of>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="concat('dataFormat', position())" select="dataFormatter" >
<!-- create style IDs for different formats -->
</xsl:variable>
<Cell>
<Data ss:Type="String">
<xsl:value-of select="title/." />
</Data>
</Cell>
</xsl:for-each>
</Row>
</xsl:template>
<xsl:template match="elements/row/column">
<xsl:for-each select="values">
<Cell>
<!-- resolve order within loop and pick correct data-type variable -->
<xsl:variable name="type" select="concat('$dataType', position())" />
<xsl:variable name="format" select="concat('$dataFormat', position())" />
<Data ss:Type="$type">
<xsl:value-of select="concat(normalize-space(.),' : ', $type)"/>
<!-- check if data format is set -->
<xsl:if test="//TODO">
<xsl:value-of select="concat(' - ', $format)" />
</xsl:if>
</Data>
</Cell>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This version is useless because I cannot use as name of variable any variable value, it must be constant value. Parsing whole data works somehow, but when I tried to implement datatype and data format it broke.
Edit: The information about datatype and dataformat is placed in head element which holds all information about columns and their headings. Columns are processed in separate template and they are not directly connected to column definitions from head element. Relation is maintained just only via elements' order. I need to process datatype and possible dataformat (which is optional) information for each row and each cell (for proper column), not only for headings.