Skip to content

ixml parser: a whitespace-only value is content, not formatting - #1226

Merged
larshp merged 1 commit into
open-abap:mainfrom
abap2UI5:claude/nifty-meitner-ema3y8
Sep 15, 2026
Merged

larshp merged 1 commit into
open-abap:mainfrom
abap2UI5:claude/nifty-meitner-ema3y8

Conversation

@oblomov-dev

@oblomov-dev oblomov-dev commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

What is wrong

if_ixml_parser~parse skips the whitespace between two tags at the end of
every iteration, src/ixml/cl_ixml.clas.locals_imp.abap:

lv_rest = lv_xml.
SHIFT lv_rest LEFT DELETING LEADING lv_whitespace.
IF lv_rest IS INITIAL OR lv_rest(1) = '<'.
  lv_xml = lv_rest.
ENDIF.

That is right for the indentation of a pretty-printed document, but it also
fires when the whitespace is everything an element contains. <FIELD> </FIELD>
and <FIELD> + LF + </FIELD> have no text node afterwards, so the value is
gone.

Through CALL TRANSFORMATION id and the parse back this is a lost value — a
string holding nothing but blanks or a line break comes back initial:

DATA lv_xml TYPE string.
DATA: BEGIN OF ls_data,
        field TYPE string,
      END OF ls_data.

ls_data-field = ` `.

CALL TRANSFORMATION id SOURCE data = ls_data RESULT XML lv_xml.
" <FIELD> </FIELD>, correct
CLEAR ls_data.
CALL TRANSFORMATION id SOURCE XML lv_xml RESULT data = ls_data.

" system: ` `, here: `` - same for a value of one line feed

The change

The skip now keeps the whitespace when it stands directly between a start tag
and its own end tag, and drops it everywhere else:

IF lv_in_element = abap_true AND lv_rest CP '</*' AND lv_rest <> lv_xml.
  " content of this element, the value branch reads it
ELSE.
  lv_xml = lv_rest.
ENDIF.

lv_in_element is set where the tag is read: true after a start tag that is
not self-closing, false after the prolog, a close tag, a self-closing tag and
a value. Whitespace before a child element (<a> + LF + <b/>) or between
two siblings stays formatting and is dropped as before — the first child of a
pretty-printed element is still the element, not a #text node.

One behaviour does change on purpose: an element that contains only
whitespace now has a text node, <a> + LF + </a> reads as a line break.
That is what a system returns, and it is the same value the document was
written from.

Tests

  • kernel_call_transformation: blank_only_roundtrip and
    newline_only_roundtrip — a value of one blank / one LF through
    CALL TRANSFORMATION id and back
  • cl_ixml: parse_blank_only_value<item> </item> keeps the blank
  • cl_ixml: parse_indented_children — indentation still does not become a
    #text node

npm test is green: abaplint: 0 issue(s) found, 735 file(s) analyzed, and
the full unit run passes.

Why it matters downstream

abap2UI5 serializes the whole app state per request with
CALL TRANSFORMATION id into the draft and parses it back on the next one
(z2ui5_cl_ui5_util_context=>xml_stringify / xml_parse), so any value the
roundtrip drops is a value the app loses. After #1225 a line break inside a
value survives; a value that is a line break, or a blank, still does not.

The parse loop skips the whitespace between two tags, which is right for the
indentation of a pretty-printed document but wrong when that whitespace is
everything an element contains: `<FIELD> </FIELD>` carries a blank and
`<FIELD>{LF}</FIELD>` a line break, and both came back as an empty string.

Through `CALL TRANSFORMATION id` and the parse back that is a lost value: a
string that holds nothing but blanks or a line break is initial afterwards.

The skip now keeps the whitespace when it stands directly between a start tag
and its own end tag, and drops it everywhere else, so indentation is read as
before - the first child of a pretty-printed element is still the element.

Tests: the asXML roundtrip of a blank-only and of a newline-only value, the
parser keeping the blank in `<item> </item>`, and indentation still not
turning into a #text node.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TKSWLpid4QLV6XWAoPixbb
@oblomov-dev oblomov-dev changed the title ixml parser: resolve numeric character references ixml parser: a whitespace-only value is content, not formatting Sep 15, 2026
@larshp
larshp merged commit 7ab3b13 into open-abap:main Sep 15, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants