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]