AP Jager wrote:With a bit of tweaking it now does exactly what it's supposed to do.
Thank you very much for letting me know of the filter setback you found! Your private message contained a quite disturbing problem:
AP Jager wrote:I did encounter a small hiccup though when processing my table to XML.
Overall it works perfectly except that when 3 or more adjacent cells are empty inside the table it will export 2 of them then ignore all other empty cells until the next cell containing text
As an example:
Let's say we have a 8 column 2 row table like:
A B C D E F G H
1 2 3 X X X X 4
(where X represents an empty cell)
I couldn't believe at first what I read. The export filter should skip empty cells? I gave it a try and found that the problem is even far more worse!Let's say we have a 3 row 8 column table like:
Code: Select all
A B C D E F G H
1 2 3 X X X X 4
1 1 2 2 X X 4 4
Where X represents not empty cells but X itself! So the cells are not empty. This is what you get by using my faulty export filter:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row>
<property name="A" value="1" row="2" col="1"/>
<property name="B" value="2" row="2" col="2"/>
<property name="C" value="3" row="2" col="3"/>
<property name="D" value="X" row="2" col="4"/>
<property name="E" value="4" row="2" col="5"/>
</row>
<row>
<property name="A" value="1" row="3" col="1"/>
<property name="B" value="2" row="3" col="2"/>
<property name="C" value="3" row="3" col="3"/>
<property name="D" value="X" row="3" col="4"/>
</row>
</rows>
Row "2" contains only
one X, misses 3 X and the "4" has the wrong name. Row "3" is even worse, because it misses 4 cells and only one cell has the correct name. So I dug into the problem and found this in the
content.xml of the above OOo Calc spreadsheet:
Code: Select all
<table:table-cell table:number-columns-repeated="4" office:value-type="string">
<text:p>X</text:p>
</table:table-cell>
The
content.xml does not contain 4 <table:table-cell><text:p>X</text:p></table:table-cell>,
but one with an attribute
table:number-columns-repeated="4". So row two of the spreadsheet does not contain 8 cells but only 5. The same applies to the last row which contains only 4 cells, each of them with
table:number-columns-repeated="2".
I tried to get around the problem but couldn't solve it completely. The following export filter uses recursion to get all the headers and the content of every cell:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<!-- We must define several namespaces, because we need them to access -->
<!-- the document model of the in-memory OpenOffice.org document. -->
<!-- If we want to access more parts of the document model, we must -->
<!-- add there namesspaces here, too. -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
exclude-result-prefixes="office table text">
<xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no"/>
<xsl:template match="/">
<!-- Process all tables -->
<tables>
<xsl:apply-templates select="//table:table"/>
</tables>
</xsl:template>
<xsl:template match="table:table">
<!-- Process table -->
<table>
<xsl:attribute name="name"><xsl:value-of select="@table:name"/></xsl:attribute>
<!-- Process all table rows -->
<xsl:for-each select="table:table-row">
<xsl:variable name="row"><xsl:number/></xsl:variable>
<xsl:choose>
<xsl:when test="position() = 1">
<header>
<xsl:attribute name="row"><xsl:value-of select="$row"/></xsl:attribute>
<!-- Process all header cells -->
<xsl:for-each select="table:table-cell">
<xsl:apply-templates select=".">
<xsl:with-param name="quantity">
<xsl:choose>
<xsl:when test="@table:number-columns-repeated">
<xsl:value-of select="@table:number-columns-repeated"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:apply-templates>
</xsl:for-each>
</header>
</xsl:when>
<xsl:otherwise>
<content>
<xsl:attribute name="row"><xsl:value-of select="$row"/></xsl:attribute>
<!-- Process all content cells -->
<xsl:for-each select="table:table-cell">
<xsl:apply-templates select=".">
<xsl:with-param name="quantity">
<xsl:choose>
<xsl:when test="@table:number-columns-repeated">
<xsl:value-of select="@table:number-columns-repeated"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:apply-templates>
</xsl:for-each>
</content>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="table:table-cell">
<xsl:param name="quantity"/>
<!-- Process table cell -->
<property>
<xsl:attribute name="value">
<xsl:choose>
<xsl:when test="@office:date-value">
<xsl:value-of select="@office:date-value"/>
</xsl:when>
<xsl:when test="@office:value">
<xsl:value-of select="@office:value"/>
</xsl:when>
<xsl:when test="normalize-space(text:p) != ''">
<xsl:value-of select="text:p"/>
</xsl:when>
<xsl:otherwise><xsl:text> </xsl:text></xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</property>
<!-- Repeat processing table cell, if there are identical table cells -->
<xsl:if test="$quantity > 1">
<xsl:apply-templates select=".">
<xsl:with-param name="quantity"><xsl:value-of select="$quantity - 1"/></xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
But this export filter has another drawback. I'm no longer able to provide the correct header for each cell. So all the export filter produces for the example above is this:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<tables>
<table name="Sheet1">
<header row="1">
<property value="a"/>
<property value="b"/>
<property value="c"/>
<property value="d"/>
<property value="e"/>
<property value="f"/>
<property value="g"/>
<property value="h"/>
</header>
<content row="2">
<property value="1"/>
<property value="2"/>
<property value="3"/>
<property value="x"/>
<property value="x"/>
<property value="x"/>
<property value="x"/>
<property value="4"/>
</content>
<content row="3">
<property value="1"/>
<property value="1"/>
<property value="2"/>
<property value="2"/>
<property value="3"/>
<property value="3"/>
<property value="x"/>
<property value="x"/>
</content>
</table>
</tables>
But, having this it is now possible by applying a second XSL to this XML to get what you expect. But as far as I know, this is no longer possible with OOo directly, unless you write a macro...