abapabap-st

Ignore closing tag in tt:group standard deserialization


As per documentation:

Only one deserialization-relevant case that does not contain a pattern can be specified.
This case is called standard deserialization.

Now the problem is that, within another tag, the standard deserialization will also match the ending tag.
Assume we have the following xml:

<X0>
   <X1>1</X1>
   <X1>2</X1>
   <X2>3</X2>
   <X2>99</X2>
   <X2>4</X2>
   <X3>5</X3>
   <X4>6</X4>
   <X2>888</X2>
</X0>.

Now with ST

<X0>
  <tt:group>
    <tt:cond frq="*">
      <X1>
        <tt:value ref="ROOT1"/>
      </X1>
    </tt:cond>
    <tt:cond frq="?">
      <X90>
        <tt:value ref="ROOT4"/>
      </X90>
    </tt:cond>
    <tt:cond frq="*">
      <tt:skip count="1"/>
    </tt:cond>
  </tt:group>
</X0>

we will exhaustibly iterate over the input XML since X90 is optional and never found. The last iteration will contain </X0>. This also matches the default serialization and will jump into this case. The result on a skip on the ending tag is a CX_ST_MATCH exception.

How can I make sure to only skip starting tags?


Solution

  • I don't know if there's a solution with <tt:skip .../>, but there is an alternative with the attribute tt:extensible="on" (the values deep-static or deep-dynamic could also be used), so that "elements that are not specified explicitly can be skipped without further processing":

    <X0 tt:extensible="on">
      <tt:group>
        <tt:cond frq="*">
          <X1>
            <tt:value ref="ROOT1"/>
          </X1>
        </tt:cond>
        <tt:cond frq="?">
          <X90>
            <tt:value ref="ROOT4"/>
          </X90>
        </tt:cond>
      </tt:group>
    </X0>
    

    NB: <X1><tt:value ref="ROOT1"/></X1> could be simplified with <X1 tt:value-ref="ROOT1"/>.