diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 99d07c91f..76eafe8e2 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -33,6 +33,7 @@ + 48070 - preserve leading and trailing white spaces in XSSFRichTextString 48044 - added implementation for CountBlank function 48036 - added IntersectionEval to allow evaluation of the intersection formula operator 47999 - avoid un-needed call to the JVM Garbage Collector when working on OOXML OPC Packages diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java index aa4e87f78..fdf23ab9a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java @@ -20,8 +20,11 @@ package org.apache.poi.xssf.usermodel; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.xssf.model.StylesTable; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlCursor; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; +import javax.xml.namespace.QName; import java.util.ArrayList; @@ -70,15 +73,16 @@ public class XSSFRichTextString implements RichTextString { private StylesTable styles; /** - * Create a rich text string and initialize it with empty string + * Create a rich text string */ public XSSFRichTextString(String str) { st = CTRst.Factory.newInstance(); st.setT(str); + preserveSpaces(st.xgetT()); } /** - * Create empty rich text string + * Create empty rich text string and initialize it with empty string */ public XSSFRichTextString() { st = CTRst.Factory.newInstance(); @@ -342,6 +346,7 @@ public class XSSFRichTextString implements RichTextString { public void setString(String s){ clearFormatting(); st.setT(s); + preserveSpaces(st.xgetT()); } /** @@ -461,4 +466,19 @@ public class XSSFRichTextString implements RichTextString { return ctFont; } + + /** + * Add the xml:spaces="preserve" attribute if the string has leading or trailing white spaces + * + * @param xs the string to check + */ + protected static void preserveSpaces(STXstring xs) { + String text = xs.getStringValue(); + if (text != null && (text.startsWith(" ") || text.endsWith(" "))) { + XmlCursor c = xs.newCursor(); + c.toNextToken(); + c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve"); + c.dispose(); + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRichTextString.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRichTextString.java index 427a56ddd..e98307959 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRichTextString.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRichTextString.java @@ -20,6 +20,7 @@ package org.apache.poi.xssf.usermodel; import junit.framework.TestCase; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXstring; /** * Tests functionality of the XSSFRichTextRun object @@ -115,4 +116,18 @@ public final class TestXSSFRichTextString extends TestCase { assertEquals(font2.getBold(), font2$.getBold()); assertEquals(font2.getFontName(), font2$.getFontName()); } + + /** + * make sure we insert xml:space="preserve" attribute + * if a string has leading or trailing white spaces + */ + public void testPreserveSpaces() { + XSSFRichTextString rt = new XSSFRichTextString("Apache"); + CTRst ct = rt.getCTRst(); + STXstring xs = ct.xgetT(); + assertEquals("Apache", xs.xmlText()); + rt.setString(" Apache"); + assertEquals(" Apache", xs.xmlText()); + + } }