pjfanning opened a new pull request, #1244:
URL: https://github.com/apache/poi/pull/1244

   String cells created an XmlBeans document store per cell on both the read 
and the write path.
   
   ### Writing: `SharedStringsTable` serialised XML to build a map key
   
   `addEntry` called `xmlText(st)` to serialise the `CTRst` to an XML fragment 
purely to use as a `HashMap` key — for every string cell written, including 
duplicates. `readFrom` did the same for every entry when opening a workbook.
   
   Entries that hold nothing but a piece of text are now keyed by that text in 
a separate map. Kept deliberately conservative:
   
   - The fast path requires `isSetT() && sizeOfRArray() == 0 && 
sizeOfRPhArray() == 0 && !isSetPhoneticPr()`; anything else keeps the existing 
XML key.
   - Plain text and XML fragments live in **separate maps**, so the two 
keyspaces cannot collide.
   - Text with leading or trailing whitespace is excluded, because for those 
entries the `xml:space="preserve"` attribute is significant but is not part of 
the text — keying by text alone could point a new cell at an entry that would 
lose its edge whitespace on save.
   - An unset `<t>` also falls back to the XML key, so `<si/>` and 
`<si><t/></si>` stay distinct.
   
   This cannot split an existing group (equal `xmlText` implies equal text for 
qualifying entries) and cannot merge two entries that would save differently. 
`count`/`uniqueCount` bookkeeping, the `strings` list and every previously 
handed-out index are untouched, and `readFrom` and `addEntry` share the 
predicate so dedup still works across an open-then-write cycle. 
`TestSharedStringsTable.testCreateNew` is the adversarial case — a plain 
`"Second string"` and a rich-run `"Second string"` — and stays correct because 
the rich one keeps the XML key.
   
   ### Reading: the event model round-tripped every string through XmlBeans
   
   `ReadOnlySharedStringsTable` stores plain `String`s, but `getItemAt` wrapped 
each in an `XSSFRichTextString` (a full `CTRst` document store) and 
`XSSFSheetXMLHandler` immediately called `toString()` to get the string back. 
The inline-string branch did `new 
XSSFRichTextString(value.toString()).toString()` on a string it already had.
   
   That round trip is **not** the identity, so it is not simply dropped: 
`toString()` applies `utfDecode`, which rewrites `_xHHHH_` escape sequences. 
The handler now applies exactly that decoding, using the same `contains("_x")` 
short-circuit and still delegating to `XSSFRichTextString` for the rare strings 
that contain it, so the result is identical in every case including nulls and 
empty strings.
   
   `getItemAt` keeps its signature, semantics and exception behaviour. The raw 
accessor added beside it is package private (the handler is in the same 
package), so nothing is added to the public `SharedStrings` interface, and 
third-party `SharedStrings` implementations keep the existing 
`getItemAt(...).toString()` path.
   
   254 tests across `xssf.model`, `xssf.eventusermodel`, `xssf.extractor`, 
`TestXSSFRichTextString` and `TestXSSFCell` pass; the full `poi-ooxml` suite 
was also run against all three of these workstreams together with no new 
failures.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to