Skip to content

ABAP Keyword Documentation →  ABAP - Reference →  Data Interfaces and Communication Interfaces →  ABAP and XML →  Class Libraries for XML →  sXML Library →  sXML Library, Examples 

sXML Library, Methods for Token-Based Parsing

This example demonstrates how various methods are used in token-based parsing.

Other versions: 7.31 | 7.40 | 7.54

Source Code

REPORT demo_sxml_token_reader_methods.

CLASS sxml_demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
  PRIVATE SECTION.
    CLASS-METHODS get_node_type
      IMPORTING node_type_int TYPE if_sxml_node=>node_type
      RETURNING value(node_type_string) TYPE string.
ENDCLASS.

CLASS sxml_demo IMPLEMENTATION.
  METHOD main.
    DATA(out) = cl_demo_output=>new( )->begin_section( `XML-Data` ).
    DATA(xml) = cl_abap_codepage=>convert_to(
     `<?xml version="1.0"?>` &&
     `<items>` &&
     `<item1 a1="11" b1="12" c1="13">1</item1>`  &&
     `<item2 a2="21" b2="22" c2="23">2</item2>`  &&
     `<item3 a3="31" b3="32" c3="33"><subItems>` &&
     `<subItem1>31</subItem1>` &&
     `<subItem2>32</subItem2>` &&
     `<subItem3>33</subItem3>` &&
     `</subItems></item3>` &&
     `<item4 a4="AA==" b4="AQ==" c4="Ag==">4</item4>` &&
     `</items>` ).
    out->write_xml( xml ).

    "Parsing all nodes
    out->next_section(
      `Parsing all Nodes of the XML-Data` ).
    DATA: BEGIN OF node,
            node_type  TYPE string,
            name       TYPE string,
            value      TYPE string,
          END OF node,
          nodes LIKE TABLE OF node.
    DATA(reader) = cl_sxml_string_reader=>create( xml ).
    TRY.
        DO.
          reader->next_node( ).
          IF reader->node_type = if_sxml_node=>co_nt_final.
            EXIT.
          ENDIF.
          APPEND VALUE #(
            node_type  = get_node_type( reader->node_type )
            name       = reader->name
            value      = reader->value ) TO nodes.
          IF reader->node_type = if_sxml_node=>co_nt_element_open.
            DO.
              reader->next_attribute( ).
              IF reader->node_type <> if_sxml_node=>co_nt_attribute.
                EXIT.
              ENDIF.
              APPEND VALUE #(
                node_type  = `attribute`
                name       = reader->name
                value      = reader->value ) TO nodes.
            ENDDO.
          ENDIF.
        ENDDO.
      CATCH cx_sxml_parse_error INTO DATA(parse_error).
        out->write_text( parse_error->get_text( ) ).
    ENDTRY.
    out->write_data( nodes ).

    "Push back node
    out->next_section( `Push Back one Node` ).
    reader = cl_sxml_string_reader=>create( xml ).
    TRY.
        DO.
          reader->next_node( ).
          IF reader->node_type = if_sxml_node=>co_nt_final.
            EXIT.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_value AND
             reader->value = 2.
            reader->push_back( ).
            DO.
              reader->next_attribute( ).
              IF reader->node_type <> if_sxml_node=>co_nt_attribute.
                EXIT.
              ENDIF.
              out->write(
                       |{ reader->name } { reader->value }| ).
            ENDDO.
            reader->next_node( ).
          ENDIF.
        ENDDO.
      CATCH cx_sxml_parse_error INTO parse_error.
        out->write_text( parse_error->get_text( ) ).
    ENDTRY.

    "Handling attributes
    out->next_section( `Handling Attributes` ).
    reader = cl_sxml_string_reader=>create( xml ).
    TRY.
        DO.
          reader->next_node( ).
          IF reader->node_type = if_sxml_node=>co_nt_final.
            EXIT.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_element_open.
            IF reader->name = 'item2'.
              reader->get_attribute_value( 'b2' ).
              out->begin_section( `Query one Attribute`
                )->write( |{ reader->name } { reader->value }|
                )->end_section( ).
            ENDIF.
            DO.
              reader->next_attribute( ).
              IF reader->node_type <> if_sxml_node=>co_nt_attribute.
                EXIT.
              ENDIF.
              IF reader->value = '33'.
                out->begin_section( `Reset Node` ).
                reader->current_node( ).
                DO.
                  reader->next_attribute( ).
                  IF reader->node_type <> if_sxml_node=>co_nt_attribute.
                    EXIT.
                  ENDIF.
                  out->write( |{ reader->name } { reader->value }| ).
                ENDDO.
                out->end_section( ).
                EXIT.
              ENDIF.
              IF reader->name = 'a4'.
                out->begin_section( `Reading Raw Values` ).
              ENDIF.
              TRY.
                  reader->next_attribute_value(
                    if_sxml_value=>co_vt_raw ).
                  out->write( |{ reader->name
                             } { reader->value
                             } { reader->value_raw }| ).
                CATCH cx_sxml_parse_error INTO parse_error.
                  CONTINUE.
              ENDTRY.
            ENDDO.
          ENDIF.
        ENDDO.
      CATCH cx_sxml_parse_error INTO parse_error.
        out->write_text( parse_error->get_text( ) ).
    ENDTRY.

    "Skip node
    out->next_section( `Skipping a Node and Getting the Subtree` ).
    reader = cl_sxml_string_reader=>create( xml ).
    DATA(writer) = CAST if_sxml_writer(
      cl_sxml_string_writer=>create(  ) ).
    DATA level TYPE i.
    TRY.
        DO.
          reader->next_node( ).
          IF reader->node_type = if_sxml_node=>co_nt_final.
            EXIT.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_element_open.
            level = level + 1.
          ELSEIF reader->node_type = if_sxml_node=>co_nt_element_close.
            level = level - 1.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_element_open AND
             level > 2.
            reader->skip_node( writer ).
            level = level - 1.
          ENDIF.
        ENDDO.
      CATCH cx_sxml_parse_error INTO parse_error.
        out->write_text( parse_error->get_text( ) ).
    ENDTRY.
    DATA(xml_sub) =
       CAST cl_sxml_string_writer( writer )->get_output(  ).
    out->write_xml( xml_sub ).

    "Skip node
    out->next_section( `Skipping a Node and Getting the Subelements` ).
    reader = cl_sxml_string_reader=>create( xml ).
    writer = CAST if_sxml_writer(
      cl_sxml_string_writer=>create(  ) ).
    writer->open_element( name = 'subElements' ).
    CLEAR level.
    TRY.
        DO.
          reader->next_node( ).
          IF reader->node_type = if_sxml_node=>co_nt_final.
            EXIT.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_element_open.
            level = level + 1.
          ELSEIF reader->node_type = if_sxml_node=>co_nt_element_close.
            level = level - 1.
          ENDIF.
          IF reader->node_type = if_sxml_node=>co_nt_element_open AND
             level > 3.
            reader->skip_node( writer ).
            level = level - 1.
          ENDIF.
        ENDDO.
      CATCH cx_sxml_parse_error INTO parse_error.
        out->write_text( parse_error->get_text( ) ).
    ENDTRY.
    writer->close_element( ).
    xml_sub =
       CAST cl_sxml_string_writer( writer )->get_output(  ).
    out->write_xml( xml_sub ).

    out->display( ).
  ENDMETHOD.
  METHOD get_node_type.
    CASE node_type_int.
      WHEN if_sxml_node=>co_nt_initial.
        node_type_string = `CO_NT_INITIAL`.
<span class="blue">*      WHEN if_sxml_node=>co_nt_comment.</span>
<span class="blue">*        node_type_string = `CO_NT_COMMENT`.</span>
      WHEN if_sxml_node=>co_nt_element_open.
        node_type_string = `CO_NT_ELEMENT_OPEN`.
      WHEN if_sxml_node=>co_nt_element_close.
        node_type_string = `CO_NT_ELEMENT_CLOSE`.
      WHEN if_sxml_node=>co_nt_value.
        node_type_string = `CO_NT_VALUE`.
      WHEN if_sxml_node=>co_nt_attribute.
        node_type_string = `CO_NT_ATTRIBUTE`.
<span class="blue">*      WHEN if_sxml_node=>co_nt_pi.</span>
<span class="blue">*        node_type_string = `CO_NT_FINAL`.</span>
      WHEN OTHERS.
        node_type_string = `Error`.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  sxml_demo=>main( ).

Description

A string of XML data is parsed more than once:

  • In the first parsing, all data is read, as usual, in a nested loop using the methods NEXT_NODE and NEXT_ATTRIBUTES.
  • In the second parsing, the method PUSH_BACK is used to move the parser back to the opened element for each value node with a specific value and to read the attributes here.
  • The third parsing demonstrates various ways of reading XML data.
  • First, a specific attribute is read for an element with a specific name using GET_ATTRIBUTE_VALUE.
  • Then an iteration runs across all attributes of all elements (without evaluating the elements) until a specific value occurs. If the value occurs, the method CURRENT_NODE is used to move the parser to the start of the current attribute list and the list is evaluated.
  • Finally, the method NEXT_ATTRIBUTE_VALUE is used to read the value of each attribute as raw data saved in Base64 format. The data is displayed only if this is successful.
  • In the fourth and fifth parsings, the method SKIP_NODE demonstrates why the hierarchy level of the current node is saved in the helper variable level.
  • In the first case, the opened element of subitems is exited using SKIP_NODE. The full subtree introduced using subitems is parsed and moved to an XML writer. The results are then displayed.
  • In the second case, the opened elements of all subelements of subitems are exited. They are parsed and their content is moved to an XML writer. These elements are located at the same level, which means the associated opened element and the closed element must added to the writer explicitly.