[XSLT] Problem with columns repeating

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
deus
Posts: 2
Joined: Sat Apr 17, 2010 3:20 pm

[XSLT] Problem with columns repeating

Post by deus »

Hello,
I have a problem with creating a simple export filter. I have a little table in OpenOffice Calc:

Code: Select all

a b c
1 2 3
4 5 6
7 9 9
The final result which i want to get is exported xml file:

Code: Select all

<table name="">
    <row>
        <a>1</a>
        <b>2</b>
        <c>3</c>
    </row>
    <row>
        <a>4</a>
        <b>5</b>
        <c>6</c>
    </row>
    <row>
        <a>7</a>
        <b>9</b>
        <c>9</c>
    </row>
</table>
The problem is, when there are cells with the same values they are saved in specific way (i checked a source of ods):

Code: Select all

<table:table-row table:style-name="ro1">
                  <table:table-cell office:value-type="float" office:value="7">
                     <text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">7</text:p>
                  </table:table-cell>
                  <table:table-cell table:number-columns-repeated="2" office:value-type="float" office:value="9">
                     <text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">9</text:p>

                  </table:table-cell>
               </table:table-row>
Using that attribute table:number-columns-repeated is very uncomfortable for solving my problem and i have no idea how to do this using XSLT. Sorry for my English and hope that someone will help me here. Thanks.
OpenOffice 3.1 on Windows XP
hol.sten
Volunteer
Posts: 495
Joined: Mon Oct 08, 2007 1:31 am
Location: Hamburg, Germany

Re: [XSLT] Problem with columns repeating

Post by hol.sten »

deus wrote:I have a problem with creating a simple export filter.
...

Code: Select all

...
                  <table:table-cell table:number-columns-repeated="2" office:value-type="float" office:value="9">
...
Using that attribute table:number-columns-repeated is very uncomfortable for solving my problem and i have no idea how to do this using XSLT.
How to handle table:number-columns-repeated has been discussed in this thread: http://user.services.openoffice.org/en/ ... =9&t=11865
OOo 3.2.0 on Ubuntu 10.04 • OOo 3.2.1 on Windows 7 64-bit and MS Windows XP
deus
Posts: 2
Joined: Sat Apr 17, 2010 3:20 pm

Re: [XSLT] Problem with columns repeating

Post by deus »

ok, after reading that topic i've tried to resolve my problem. It works fine for table with non-repeating values but with repeating it won't. Can someone take a look for my xslt export file and tell me what i'm doing wrong?

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<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" standalone="yes"/>

<xsl:template match="/">
	<xsl:for-each select="//table:table">
		<xsl:if test="./table:table-row[2]">
			<TABLE>
				<xsl:attribute name="name"><xsl:value-of select="@table:name"/></xsl:attribute>
				<xsl:apply-templates select="."/>
			</TABLE>
		</xsl:if>
	</xsl:for-each>
</xsl:template>

<xsl:template match="table:table">
	<xsl:for-each select="table:table-row">
		<xsl:call-template name="wiersze" />
	</xsl:for-each>
</xsl:template>

<xsl:template name="wiersze">
	<xsl:if test="position()>1">
		<ROW>
			<xsl:for-each select="table:table-cell">
				<xsl:apply-templates select=".">
					<xsl:with-param name="column"><xsl:number/></xsl:with-param>
				</xsl:apply-templates>
			</xsl:for-each>
		</ROW>
	</xsl:if>
</xsl:template>

<xsl:template match="table:table-cell">
	<xsl:param name="column"/>
	<xsl:choose>
		<xsl:when test="@table:number-columns-repeated">
			<xsl:variable name="numcols" select="number(@table:number-columns-repeated)"/>
			<xsl:call-template name="processcol">
				<xsl:with-param name="tagName">
					<xsl:for-each select="./../../table:table-row[1]/table:table-cell">
						<xsl:if test="position() = $column">
							<xsl:choose>
								<xsl:when test="normalize-space(text:p) != ''">
									<xsl:choose>
										<xsl:when test="matches(normalize-space(text:p),'^[a-zA-Z]')">
											<xsl:value-of select="text:p"/>
										</xsl:when>
										<xsl:otherwise>col_<xsl:value-of select="text:p"/></xsl:otherwise>
									</xsl:choose>
								</xsl:when>
								<xsl:otherwise>col_<xsl:value-of select="$column"/></xsl:otherwise>
							</xsl:choose>
						</xsl:if>
					</xsl:for-each>
				</xsl:with-param>
				<xsl:with-param name="tagContent">
					<xsl:choose>
						<xsl:when test="normalize-space(text:p) != ''">
							<xsl:value-of select="text:p"/>
						</xsl:when>
					</xsl:choose>
				</xsl:with-param>
				<xsl:with-param name="currentCol" select="0"/>
				<xsl:with-param name="totalCols" select="$numcols"/>
			</xsl:call-template>
		</xsl:when>
		<xsl:otherwise>
			<xsl:call-template name="komorki">
				<xsl:with-param name="tagName">
					<xsl:for-each select="./../../table:table-row[1]/table:table-cell">
						<xsl:if test="position() = $column">
							<xsl:choose>
								<xsl:when test="normalize-space(text:p) != ''">
									<xsl:choose>
										<xsl:when test="matches(normalize-space(text:p),'^[a-zA-Z]')">
											<xsl:value-of select="text:p"/>
										</xsl:when>
										<xsl:otherwise>col_<xsl:value-of select="text:p"/></xsl:otherwise>
									</xsl:choose>
								</xsl:when>
								<xsl:otherwise>col_<xsl:value-of select="$column"/></xsl:otherwise>
							</xsl:choose>
						</xsl:if>
					</xsl:for-each>
				</xsl:with-param>
				<xsl:with-param name="tagContent">
					<xsl:choose>
						<xsl:when test="normalize-space(text:p) != ''">
							<xsl:value-of select="text:p"/>
						</xsl:when>
					</xsl:choose>
				</xsl:with-param>
			</xsl:call-template>
		</xsl:otherwise>
	</xsl:choose>

</xsl:template>

<xsl:template name="komorki">
	<xsl:param name="tagName"/>
	<xsl:param name="tagContent"/>
	<xsl:element name="{$tagName}"><xsl:value-of select="$tagContent"/></xsl:element>
</xsl:template>

<xsl:template name="processcol">
	<xsl:param name="currentCol"/>
    <xsl:param name="totalCols"/> 
	<xsl:param name="tagName"/>
	<xsl:param name="tagContent"/>
	<xsl:choose>
		<xsl:when test="$currentCol < $totalCols">
			<xsl:element name="{$tagName}"><xsl:value-of select="$tagContent"/></xsl:element>
			<xsl:call-template name="processcol">
				<xsl:with-param name="currentCol" select="$currentCol + 1"/>
				<xsl:with-param name="totalCols" select="$totalCols"/>
			</xsl:call-template>
		</xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>
OpenOffice 3.1 on Windows XP
hol.sten
Volunteer
Posts: 495
Joined: Mon Oct 08, 2007 1:31 am
Location: Hamburg, Germany

Re: [XSLT] Problem with columns repeating

Post by hol.sten »

deus wrote:Can someone take a look for my xslt export file and tell me what i'm doing wrong?
I gave your XSLT filter a try. Your problem lies in the processcol template. If your test test="$currentCol < $totalCols" results in true, you call the processcol template with the wrong number of parameters. This xslt filter at least processes repeating values without an error, although the tags are wrong:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<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" standalone="yes"/>

<xsl:template match="/">
   <xsl:for-each select="//table:table">
      <xsl:if test="./table:table-row[2]">
         <TABLE>
            <xsl:attribute name="name"><xsl:value-of select="@table:name"/></xsl:attribute>
            <xsl:apply-templates select="."/>
         </TABLE>
      </xsl:if>
   </xsl:for-each>
</xsl:template>

<xsl:template match="table:table">
   <xsl:for-each select="table:table-row">
      <xsl:call-template name="wiersze" />
   </xsl:for-each>
</xsl:template>

<xsl:template name="wiersze">
   <xsl:if test="position()>1">
      <ROW>
         <xsl:for-each select="table:table-cell">
            <xsl:apply-templates select=".">
               <xsl:with-param name="column"><xsl:number/></xsl:with-param>
            </xsl:apply-templates>
         </xsl:for-each>
      </ROW>
   </xsl:if>
</xsl:template>

<xsl:template match="table:table-cell">
   <xsl:param name="column"/>
   <xsl:choose>
      <xsl:when test="@table:number-columns-repeated">
         <xsl:variable name="numcols" select="number(@table:number-columns-repeated)"/>
         <xsl:call-template name="processcol">
            <xsl:with-param name="currentCol" select="0"/>
            <xsl:with-param name="totalCols" select="$numcols"/>
            <xsl:with-param name="tagName">
               <xsl:for-each select="./../../table:table-row[1]/table:table-cell">
                  <xsl:if test="position() = $column">
                     <xsl:choose>
                        <xsl:when test="normalize-space(text:p) != ''">
                           <xsl:choose>
                              <xsl:when test="matches(normalize-space(text:p),'^[a-zA-Z]')">
                                 <xsl:value-of select="text:p"/>
                              </xsl:when>
                              <xsl:otherwise>col_<xsl:value-of select="text:p"/></xsl:otherwise>
                           </xsl:choose>
                        </xsl:when>
                        <xsl:otherwise>col_<xsl:value-of select="$column"/></xsl:otherwise>
                     </xsl:choose>
                  </xsl:if>
               </xsl:for-each>
            </xsl:with-param>
            <xsl:with-param name="tagContent">
               <xsl:choose>
                  <xsl:when test="normalize-space(text:p) != ''">
                     <xsl:value-of select="text:p"/>
                  </xsl:when>
               </xsl:choose>
            </xsl:with-param>
         </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
         <xsl:call-template name="komorki">
            <xsl:with-param name="tagName">
               <xsl:for-each select="./../../table:table-row[1]/table:table-cell">
                  <xsl:if test="position() = $column">
                     <xsl:choose>
                        <xsl:when test="normalize-space(text:p) != ''">
                           <xsl:choose>
                              <xsl:when test="matches(normalize-space(text:p),'^[a-zA-Z]')">
                                 <xsl:value-of select="text:p"/>
                              </xsl:when>
                              <xsl:otherwise>col_<xsl:value-of select="text:p"/></xsl:otherwise>
                           </xsl:choose>
                        </xsl:when>
                        <xsl:otherwise>col_<xsl:value-of select="$column"/></xsl:otherwise>
                     </xsl:choose>
                  </xsl:if>
               </xsl:for-each>
            </xsl:with-param>
            <xsl:with-param name="tagContent">
               <xsl:choose>
                  <xsl:when test="normalize-space(text:p) != ''">
                     <xsl:value-of select="text:p"/>
                  </xsl:when>
               </xsl:choose>
            </xsl:with-param>
         </xsl:call-template>
      </xsl:otherwise>
   </xsl:choose>

</xsl:template>

<xsl:template name="komorki">
   <xsl:param name="tagName"/>
   <xsl:param name="tagContent"/>
   <xsl:element name="{$tagName}"><xsl:value-of select="$tagContent"/></xsl:element>
</xsl:template>

<xsl:template name="processcol">
   <xsl:param name="currentCol"/>
   <xsl:param name="totalCols"/>
   <xsl:param name="tagName"/>
   <xsl:param name="tagContent"/>
   <xsl:choose>
      <xsl:when test="$currentCol < $totalCols">
         <xsl:element name="{$tagName}"><xsl:value-of select="$tagContent"/></xsl:element>
         <xsl:call-template name="processcol">
            <xsl:with-param name="currentCol" select="$currentCol + 1"/>
            <xsl:with-param name="totalCols" select="$totalCols"/>
            <xsl:with-param name="tagName" select="$tagName"/>
            <xsl:with-param name="tagContent" select="$tagContent"/>
         </xsl:call-template>
      </xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>
The above xslt filter applied on:

Code: Select all

 a    b    c    d
 1    2    3    4
 5    6    7    8
 9    9    9    9
10   10   11   11
12   12   12   13
14   15   15   15
results in this xml file:

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TABLE name="Sheet1">
   <ROW>
      <a>1</a>
      <b>2</b>
      <c>3</c>
      <d>4</d>
   </ROW>
   <ROW>
      <a>5</a>
      <b>6</b>
      <c>7</c>
      <d>8</d>
   </ROW>
   <ROW>
      <a>9</a>
      <a>9</a>
      <a>9</a>
      <a>9</a>
   </ROW>
   <ROW>
      <a>10</a>
      <a>10</a>
      <b>11</b>
      <b>11</b>
   </ROW>
   <ROW>
      <a>12</a>
      <a>12</a>
      <a>12</a>
      <b>13</b>
   </ROW>
   <ROW>
      <a>14</a>
      <b>15</b>
      <b>15</b>
      <b>15</b>
   </ROW>
</TABLE>
Sorry, but I found no way how to fix the tag names, too.
OOo 3.2.0 on Ubuntu 10.04 • OOo 3.2.1 on Windows 7 64-bit and MS Windows XP
Post Reply