52311 - Conversion to html : Problem in titles number

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1405808 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2012-11-05 14:38:12 +00:00
parent b5876021e7
commit c3f572e2cd
8 changed files with 177 additions and 100 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.9-beta1" date="2012-??-??"> <release version="3.9-beta1" date="2012-??-??">
<action dev="poi-developers" type="fix">52311 - Conversion to html : Problem in titles number </action>
<action dev="poi-developers" type="fix">53914 - TableRow#getTopBorder() return bottom's border</action> <action dev="poi-developers" type="fix">53914 - TableRow#getTopBorder() return bottom's border</action>
<action dev="poi-developers" type="fix">53282 - Avoid exception when parsing OPC relationships with non-breaking spaces</action> <action dev="poi-developers" type="fix">53282 - Avoid exception when parsing OPC relationships with non-breaking spaces</action>
<action dev="poi-developers" type="fix">54016 - Avoid exception when parsing workbooks with DConRefRecord in row aggregate</action> <action dev="poi-developers" type="fix">54016 - Avoid exception when parsing workbooks with DConRefRecord in row aggregate</action>

View File

@ -226,13 +226,15 @@ public class AbstractWordUtils
return stringBuilder.toString(); return stringBuilder.toString();
} }
public static class NumberingState { public static class NumberingState
{
private final Map<String, Integer> levels = new HashMap<String, Integer>(); private final Map<String, Integer> levels = new HashMap<String, Integer>();
} }
public static String getBulletText(NumberingState numberingState, HWPFList list, char level ) public static String getBulletText( NumberingState numberingState,
HWPFList list, char level )
{ {
StringBuffer bulletBuffer = new StringBuffer(); StringBuffer bulletBuffer = new StringBuffer();
char[] xst = list.getNumberText( level ).toCharArray(); char[] xst = list.getNumberText( level ).toCharArray();
@ -240,25 +242,38 @@ public class AbstractWordUtils
{ {
if ( element < 9 ) if ( element < 9 )
{ {
final String key = list.getLsid() + "#" + ( (int) element ); int lsid = list.getLsid();
final String key = lsid + "#" + ( (int) element );
int num; int num;
if ( numberingState.levels.containsKey( key ) )
if ( !list.isStartAtOverriden( element )
&& numberingState.levels.containsKey( key ) )
{ {
num = numberingState.levels.get( key ).intValue(); num = numberingState.levels.get( key ).intValue();
if ( level == element )
{
num++;
numberingState.levels.put( key, Integer.valueOf( num ) );
}
} }
else else
{ {
num = list.getStartAt( level ); num = list.getStartAt( element );
numberingState.levels.put( key, Integer.valueOf( num ) ); numberingState.levels.put( key, Integer.valueOf( num ) );
} }
if ( level == element )
{
// cleaning states of nested levels to reset numbering
for ( int i = element + 1; i < 9; i++ )
{
final String childKey = lsid + "#" + i;
numberingState.levels.remove( childKey );
}
}
bulletBuffer.append( NumberFormatter.getNumber( num, bulletBuffer.append( NumberFormatter.getNumber( num,
list.getNumberFormat( level ) ) ); list.getNumberFormat( level ) ) );
if ( level == element )
{
numberingState.levels.put( key, Integer.valueOf( num + 1 ) );
}
} }
else else
{ {

View File

@ -14,11 +14,12 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hwpf.model.types; package org.apache.poi.hwpf.model.types;
import org.apache.poi.util.BitField; import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.util.Internal; import org.apache.poi.util.*;
/** /**
* The grfhic structure is a set of HTML incompatibility flags that specify the HTML * The grfhic structure is a set of HTML incompatibility flags that specify the HTML
@ -108,9 +109,10 @@ public abstract class GrfhicAbstractType
public String toString() public String toString()
{ {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("[Grfhic]\n"); builder.append("[Grfhic]\n");
builder.append( " .grfhic = " ); builder.append( " .grfhic = " );
builder.append(" (").append(getGrfhic()).append(" )\n"); builder.append(" ( ").append( field_1_grfhic ).append( " )\n" );
builder.append(" .fHtmlChecked = ").append(isFHtmlChecked()).append('\n'); builder.append(" .fHtmlChecked = ").append(isFHtmlChecked()).append('\n');
builder.append(" .fHtmlUnsupported = ").append(isFHtmlUnsupported()).append('\n'); builder.append(" .fHtmlUnsupported = ").append(isFHtmlUnsupported()).append('\n');
builder.append(" .fHtmlListTextNotSharpDot = ").append(isFHtmlListTextNotSharpDot()).append('\n'); builder.append(" .fHtmlListTextNotSharpDot = ").append(isFHtmlListTextNotSharpDot()).append('\n');
@ -120,7 +122,7 @@ public abstract class GrfhicAbstractType
builder.append(" .fHtmlHangingIndentBeneathNumber = ").append(isFHtmlHangingIndentBeneathNumber()).append('\n'); builder.append(" .fHtmlHangingIndentBeneathNumber = ").append(isFHtmlHangingIndentBeneathNumber()).append('\n');
builder.append(" .fHtmlBuiltInBullet = ").append(isFHtmlBuiltInBullet()).append('\n'); builder.append(" .fHtmlBuiltInBullet = ").append(isFHtmlBuiltInBullet()).append('\n');
builder.append("[/Grfhic]\n"); builder.append("[/Grfhic]");
return builder.toString(); return builder.toString();
} }

View File

@ -21,20 +21,19 @@ import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
* List Format Override (LFO). * List Format Override (LFO). <p>Class and fields descriptions are quoted from
[MS-DOC] --v20110315; Word (.doc) Binary File Format
* <p> * <p>
* Class and fields descriptions are quoted from [MS-DOC] --v20110315; Word * NOTE: This source is automatically generated please do not modify this file. Either subclass or
* (.doc) Binary File Format * remove the record in src/types/definitions.
*
* <p>
* NOTE: This source is automatically generated please do not modify this file.
* Either subclass or remove the record in src/types/definitions.
* <p> * <p>
* This class is internal. It content or properties may change without notice * This class is internal. It content or properties may change without notice
* due to changes in our knowledge of internal Microsoft Word binary structures. * due to changes in our knowledge of internal Microsoft Word binary structures.
*
* @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) Binary File Format;
* Binary File Format; Copyright (c) Microsoft Corporation Copyright (c) Microsoft Corporation
*/ */
@Internal @Internal
public abstract class LFOAbstractType public abstract class LFOAbstractType
@ -132,7 +131,8 @@ public abstract class LFOAbstractType
result = prime * result + field_3_unused2; result = prime * result + field_3_unused2;
result = prime * result + field_4_clfolvl; result = prime * result + field_4_clfolvl;
result = prime * result + field_5_ibstFltAutoNum; result = prime * result + field_5_ibstFltAutoNum;
result = prime * result + field_6_grfhic.hashCode(); result = prime * result
+ ((field_6_grfhic == null) ? 0 : field_6_grfhic.hashCode());
result = prime * result + field_7_unused3; result = prime * result + field_7_unused3;
return result; return result;
} }
@ -140,30 +140,29 @@ public abstract class LFOAbstractType
public String toString() public String toString()
{ {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("[LFO]\n"); builder.append("[LFO]\n");
builder.append( " .lsid = " ); builder.append( " .lsid = " );
builder.append( " (" ).append( getLsid() ).append( " )\n" ); builder.append(" ( ").append( field_1_lsid ).append( " )\n" );
builder.append( " .unused1 = " ); builder.append( " .unused1 = " );
builder.append( " (" ).append( getUnused1() ).append( " )\n" ); builder.append(" ( ").append( field_2_unused1 ).append( " )\n" );
builder.append( " .unused2 = " ); builder.append( " .unused2 = " );
builder.append( " (" ).append( getUnused2() ).append( " )\n" ); builder.append(" ( ").append( field_3_unused2 ).append( " )\n" );
builder.append( " .clfolvl = " ); builder.append( " .clfolvl = " );
builder.append( " (" ).append( getClfolvl() ).append( " )\n" ); builder.append(" ( ").append( field_4_clfolvl ).append( " )\n" );
builder.append( " .ibstFltAutoNum = " ); builder.append( " .ibstFltAutoNum = " );
builder.append( " (" ).append( getIbstFltAutoNum() ).append( " )\n" ); builder.append(" ( ").append( field_5_ibstFltAutoNum ).append( " )\n" );
builder.append( " .grfhic = " ); builder.append( " .grfhic = " );
builder.append( " (" ).append( getGrfhic() ).append( " )\n" ); builder.append(" ( ").append( field_6_grfhic == null ? "null" : field_6_grfhic.toString().replaceAll( "\n", "\n " ) ).append( " )\n" );
builder.append( " .unused3 = " ); builder.append( " .unused3 = " );
builder.append( " (" ).append( getUnused3() ).append( " )\n" ); builder.append(" ( ").append( field_7_unused3 ).append( " )\n" );
builder.append( "[/LFO]\n" ); builder.append("[/LFO]");
return builder.toString(); return builder.toString();
} }
/** /**
* A signed integer that specifies the list identifier of an LSTF. This LFO * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value..
* corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is
* equal to this value..
*/ */
@Internal @Internal
public int getLsid() public int getLsid()
@ -172,9 +171,7 @@ public abstract class LFOAbstractType
} }
/** /**
* A signed integer that specifies the list identifier of an LSTF. This LFO * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value..
* corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is
* equal to this value..
*/ */
@Internal @Internal
public void setLsid( int field_1_lsid ) public void setLsid( int field_1_lsid )

View File

@ -28,6 +28,7 @@ import org.apache.poi.util.Internal;
import org.apache.poi.hwpf.model.LFO; import org.apache.poi.hwpf.model.LFO;
import org.apache.poi.hwpf.model.LFOData; import org.apache.poi.hwpf.model.LFOData;
import org.apache.poi.hwpf.model.ListData; import org.apache.poi.hwpf.model.ListData;
import org.apache.poi.hwpf.model.ListFormatOverrideLevel;
import org.apache.poi.hwpf.model.ListLevel; import org.apache.poi.hwpf.model.ListLevel;
import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.hwpf.model.StyleSheet;
import org.apache.poi.hwpf.sprm.CharacterSprmCompressor; import org.apache.poi.hwpf.sprm.CharacterSprmCompressor;
@ -167,6 +168,11 @@ public final class HWPFList
public int getStartAt( char level ) public int getStartAt( char level )
{ {
if ( isStartAtOverriden( level ) )
{
return _lfoData.getRgLfoLvl()[level].getIStartAt();
}
return getLVL( level ).getStartAt(); return getLVL( level ).getStartAt();
} }
@ -183,6 +189,15 @@ public final class HWPFList
return _ignoreLogicalLeftIdentation; return _ignoreLogicalLeftIdentation;
} }
public boolean isStartAtOverriden( char level )
{
ListFormatOverrideLevel lfolvl = _lfoData.getRgLfoLvl().length > level ? _lfoData
.getRgLfoLvl()[level] : null;
return lfolvl != null && lfolvl.getIStartAt() != 0
&& !lfolvl.isFormatting();
}
public void setIgnoreLogicalLeftIdentation( public void setIgnoreLogicalLeftIdentation(
boolean ignoreLogicalLeftIdentation ) boolean ignoreLogicalLeftIdentation )
{ {

View File

@ -36,6 +36,21 @@ public class TestWordToTextConverter extends TestCase
.contains( "Soak the rice in water for three to four hours" ) ); .contains( "Soak the rice in water for three to four hours" ) );
} }
public void testBug52311() throws Exception
{
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug52311.doc" );
String result = WordToTextConverter.getText( doc );
assertTrue( result.contains( "2.1\tHeader 2.1" ) );
assertTrue( result.contains( "2.2\tHeader 2.2" ) );
assertTrue( result.contains( "2.3\tHeader 2.3" ) );
assertTrue( result.contains( "2.3.1\tHeader 2.3.1" ) );
assertTrue( result.contains( "2.99\tHeader 2.99" ) );
assertTrue( result.contains( "2.99.1\tHeader 2.99.1" ) );
assertTrue( result.contains( "2.100\tHeader 2.100" ) );
assertTrue( result.contains( "2.101\tHeader 2.101" ) );
}
public void testBug53380_3() throws Exception public void testBug53380_3() throws Exception
{ {
HWPFDocument doc = HWPFTestDataSamples HWPFDocument doc = HWPFTestDataSamples

View File

@ -381,27 +381,8 @@ public abstract class </xsl:text><xsl:call-template name="outputClassName"/><xsl
<xsl:call-template name="linebreak"/> <xsl:call-template name="linebreak"/>
<xsl:call-template name="linebreak"/> <xsl:call-template name="linebreak"/>
<xsl:call-template name="indent"/>
<xsl:text>public String toString() <xsl:call-template name="toString" />
{
StringBuilder builder = new StringBuilder();
</xsl:text>
<xsl:call-template name="indent"/>
<xsl:call-template name="indent"/>
<xsl:text>builder.append("[</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>]\n");</xsl:text>
<xsl:call-template name="linebreak"/>
<xsl:apply-templates select="//field" mode="tostring"/>
<xsl:call-template name="linebreak"/>
<xsl:call-template name="indent"/>
<xsl:call-template name="indent"/>
<xsl:text>builder.append("[/</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>]\n");
return builder.toString();
}
</xsl:text>
<xsl:apply-templates select="//field" mode="getset"/> <xsl:apply-templates select="//field" mode="getset"/>
<xsl:apply-templates select="//field" mode="bits"/> <xsl:apply-templates select="//field" mode="bits"/>
@ -549,19 +530,70 @@ public abstract class </xsl:text><xsl:call-template name="outputClassName"/><xsl
} }
</xsl:template> </xsl:template>
<xsl:template name="toString">
<xsl:call-template name="indent" />
<xsl:text>public String toString()</xsl:text>
<xsl:call-template name="linebreak" />
<xsl:call-template name="indent" />
<xsl:text>{</xsl:text>
<xsl:call-template name="linebreak" />
<xsl:call-template name="indent" />
<xsl:call-template name="indent" />
<xsl:text>StringBuilder builder = new StringBuilder();</xsl:text>
<xsl:call-template name="linebreak" />
<xsl:call-template name="linebreak" />
<xsl:call-template name="indent" />
<xsl:call-template name="indent" />
<xsl:text>builder.append("[</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>]\n");</xsl:text>
<xsl:call-template name="linebreak" />
<xsl:apply-templates select="//field" mode="tostring" />
<xsl:call-template name="linebreak" />
<xsl:call-template name="indent" />
<xsl:call-template name="indent" />
<xsl:text>builder.append("[/</xsl:text>
<xsl:value-of select="@name" />
<xsl:text>]");
return builder.toString();
}
</xsl:text>
</xsl:template>
<xsl:template match="field" mode="tostring"> <xsl:template match="field" mode="tostring">
<xsl:variable name="fieldName"
select="recutil:getFieldName(position(),@name,0)" />
<xsl:call-template name="indent" /> <xsl:call-template name="indent" />
<xsl:call-template name="indent" /> <xsl:call-template name="indent" />
<xsl:text>builder.append( " .</xsl:text> <xsl:text>builder.append( " .</xsl:text>
<xsl:value-of select="recutil:getFieldName(@name,20)" /> <xsl:value-of select="recutil:getFieldName(@name,20)" />
<xsl:text> = " );</xsl:text> <xsl:text> = " );</xsl:text>
<xsl:call-template name="linebreak" /> <xsl:call-template name="linebreak" />
<xsl:call-template name="indent" /> <xsl:call-template name="indent" />
<xsl:call-template name="indent" /> <xsl:call-template name="indent" />
<xsl:text>builder.append(" (").append(get</xsl:text> <xsl:text>builder.append(" ( ").append( </xsl:text>
<xsl:value-of select="recutil:getFieldName1stCap(@name,0)"/> <xsl:choose>
<xsl:text>()).append(" )\n");</xsl:text> <xsl:when
test="@type='boolean' or @type='byte' or @type='double' or @type='int' or @type='long' or @type='short'">
<xsl:value-of select="$fieldName" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$fieldName" />
<xsl:text> == null ? "null" : </xsl:text>
<xsl:value-of select="$fieldName" />
<xsl:text>.toString().replaceAll( "\n", "\n " )</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text> ).append( " )\n" );</xsl:text>
<xsl:call-template name="linebreak" /> <xsl:call-template name="linebreak" />
<xsl:apply-templates select="bit" mode="bittostring" /> <xsl:apply-templates select="bit" mode="bittostring" />
</xsl:template> </xsl:template>

Binary file not shown.