[ABAP] XML-Strings parsen

Variante 1 (IF_IXML_ELEMENT, IF_IXML_NODE_COLLECTION)

* XML-Daten
DATA(lv_xml) = |<object>| &&
               |  <str name="text">abcd</str>| &&
               |  <bool name="flag">true</bool>| &&
               |  <member name="number"><num>111</num></member>| &&
               |  <member name="content"><null /></member>| &&
               |  <member name="attr"></member>| &&
               |</object>|.

* XML-Interface
DATA(o_ixml) = cl_ixml=>create( ).
* XML-Doc
DATA(o_doc) = o_ixml->create_document( ).
* Stream-Factory
DATA(o_sf) = o_ixml->create_stream_factory( ).
* Stream
DATA(o_stream) = o_sf->create_istream_string( string = lv_xml ).

* Parser-Objekt erzeugen
DATA(o_parser) = o_ixml->create_parser( document       = o_doc
                                        istream        = o_stream
                                        stream_factory = o_sf ).

* XML parsen
IF o_parser->parse( ) = 0.
* Root-Node
  DATA(o_root) = o_doc->get_root_element( ).

* Alle Nodes mit Namen 'member'
  DATA(o_nodes_member) = o_root->get_elements_by_tag_name( name = 'member' ).
* Iterator für die gefundenen Nodes
  DATA(o_node_iterator_members) = o_nodes_member->create_iterator( ).
* ersten Iterator-Wert holen
  DATA(o_nodes_temp) = o_node_iterator_members->get_next( ).

* Iterator durchgehen
  WHILE NOT o_nodes_temp IS INITIAL.
* Wert der Node ausgeben
    WRITE: / o_nodes_temp->get_value( ).

* Attribute
    DATA(o_note_temp_attr) = o_nodes_temp->get_attributes( ).
    DATA(o_node_temp_item) = o_note_temp_attr->get_named_item( 'name' ).
    IF o_node_temp_item IS BOUND.
      WRITE: / o_node_temp_item->get_value( ).
    ENDIF.

* Children
    DATA(o_node_temp_children) = o_nodes_temp->get_children( ).
    WRITE: / 'Childrens:', o_node_temp_children->get_length( ).

* nächster Iterator-Wert
    o_nodes_temp = o_node_iterator_members->get_next( ).
  ENDWHILE.
ELSE.
* Fehlerauswertung
  DO o_parser->num_errors( ) TIMES.
    DATA(o_err) = o_parser->get_error( index = sy-index - 1 ).
    IF o_err IS BOUND.
      WRITE: / o_err->get_column( ), o_err->get_line( ), o_err->get_reason( ).
    ENDIF.
  ENDDO.
ENDIF.

Variante 2 (find_from_name)

* XML-Daten
DATA(lv_xml) = |<object>| &&
               |  <str name="text">abcd</str>| &&
               |  <bool name="flag">true</bool>| &&
               |  <member name="number"><num>111</num></member>| &&
               |  <member name="content"><null /></member>| &&
               |  <member name="attr"></member>| &&
               |</object>|.

* XML-Interface
DATA(o_ixml) = cl_ixml=>create( ).
* XML-Doc
DATA(o_doc) = o_ixml->create_document( ).
* Stream-Factory
DATA(o_sf) = o_ixml->create_stream_factory( ).
* Stream
DATA(o_stream) = o_sf->create_istream_string( string = lv_xml ).

* Parser-Objekt erzeugen
DATA(o_parser) = o_ixml->create_parser( document       = o_doc
                                        istream        = o_stream
                                        stream_factory = o_sf ).

* XML parsen
IF o_parser->parse( ) = 0.
* <object>
  DATA(o_root) = o_doc->find_from_name( 'object' ).

  IF o_root IS BOUND.
* <str ...>
    DATA(o_str) = o_root->get_first_child( ).
    IF o_str IS BOUND.
* Wert der Node ausgeben
      WRITE: / o_str->get_value( ).

* Attribut 'name'
      DATA(o_attr) = o_str->get_attributes( ).
      DATA(o_name) = o_attr->get_named_item( 'name' ).
      IF o_name IS BOUND.
        WRITE: / o_name->get_value( ).
      ENDIF.
    ENDIF.
  ENDIF.
ELSE.
* Fehlerauswertung
  DO o_parser->num_errors( ) TIMES.
    DATA(o_err) = o_parser->get_error( index = sy-index - 1 ).
    IF o_err IS BOUND.
      WRITE: / o_err->get_column( ), o_err->get_line( ), o_err->get_reason( ).
    ENDIF.
  ENDDO.
ENDIF.

[ABAP] PDF-Dokument per ADS (Adobe Document Service) in XML konvertieren

* https://www.berater-wiki.de/XML_aus_PDF_extrahieren_mit_Testprogramm_FP_PDF_TEST_03
* http://sapfirst.blogspot.com/2014/05/inbound-abap-proxy-with-pdf-attachment.html
* Paket:     SAFP
* Programme: FP_PDF_TEST_01 (PDF erzeugen)
*            FP_PDF_TEST_03 (Datenextraktion)
* XFD (XML Form Data): https://www.berater-wiki.de/XFD-Datei_(Values_of_PDF_form_fields_in_XML)
* XFT (XML Form Template)
* XDC (XML Printer Definitions)

TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  file_filter    = |pdf (*.pdf)\|*.pdf\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING
                                                  file_table  = it_files
                                                  rc          = lv_rc
                                                  user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn mind. zwei Dateien ausgewählt worden sind
      IF lines( it_files ) > 0.
        DATA(lv_filesize) = CONV w3param-cont_len( '0' ).
        DATA(it_bin_data) = VALUE w3mimetabtype( ).

* Datei auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING
                                                filename   = |{ it_files[ 1 ]-filename }|
                                                filetype   = 'BIN'
                                              IMPORTING
                                                filelength = lv_filesize
                                              CHANGING
                                                data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* Form Processor erzeugen
        DATA(o_form_processor) = cl_fp=>get_reference( ).
* PDF-Objekt erzeugen
        DATA(o_pdf) = o_form_processor->create_pdf_object( ).
* Binärdaten an PDF-Objekt übergeben
        o_pdf->set_document( pdfdata = lv_bin_data ).
* PDF-Daten extrahieren
        o_pdf->set_extractdata( ).
* ADS-Server rufen
        o_pdf->execute( ).
* extrahierte Daten holen (xstring)
        o_pdf->get_data( IMPORTING formdata = DATA(lv_pdf_formdata) ).

* xstring (binary) -> XML-string (UTF-8)
        DATA(lv_pdf_xml_str) = ||.
        DATA(o_conv) = cl_abap_conv_in_ce=>create( input    = lv_pdf_formdata
                                                   encoding = 'UTF-8' ).
        o_conv->read( IMPORTING data = lv_pdf_xml_str ).

* XML-Zugriff
        DATA(o_ixml) = cl_ixml=>create( ).

        DATA(o_sf) = o_ixml->create_stream_factory( ).
        DATA(o_doc) = o_ixml->create_document( ).
        DATA(o_stream) = o_sf->create_istream_string( lv_pdf_xml_str ).

* XML-Parser
        DATA(o_parser) = o_ixml->create_parser( stream_factory = o_sf
                                                istream        = o_stream
                                                document       = o_doc ).

* XML parsen
        IF o_parser->parse( ) = 0.

          DATA(o_root) = o_doc->get_root_element( ).

          ...

        ELSE.
* Fehlerauswertung
          DO o_parser->num_errors( ) TIMES.
            DATA(o_err) = o_parser->get_error( index = sy-index - 1 ).
            IF o_err IS BOUND.
              WRITE: / o_err->get_column( ), o_err->get_line( ), o_err->get_reason( ).
            ENDIF.
          ENDDO.
        ENDIF.

      ENDIF.
    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

[ABAP] XML-Daten in eine Datei (*.xml) schreiben

Variante 1 (lokal über XML-String)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).

  ...

* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* XML-String
  DATA: lv_xml TYPE string.

* Stream für Ausgabe in XML-String
  DATA(o_stream) = o_sf->create_ostream_cstring( lv_xml ).
  o_stream->set_encoding( encoding = o_encoding ).
  o_stream->set_pretty_print( pretty_print = abap_true ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

* XML-String in lv_xml generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
  * XML-String in XML-Document wandeln
    DATA(o_xml_doc) = NEW cl_xml_document( ).
    o_xml_doc->parse_string( lv_xml ).

  * XML-Document als Datei speichern
    o_xml_doc->export_to_file( 'c:\temp\test.xml' ).
  ENDIF.

Variante 2 (lokal über XML-iTab)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).

  ...

* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* XML-iTab
  DATA: it_xml_out TYPE STANDARD TABLE OF char255 WITH DEFAULT KEY.

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* Stream für Ausgabe in XML-iTab
  DATA(o_stream) = o_sf->create_ostream_itable( table = it_xml_out ).
  o_stream->set_encoding( encoding = o_encoding ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

  o_render->set_normalizing( is_normalizing = space ).

* XML-String in it_xml_out generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
* Tabelle als Binär-Daten herunterladen
    cl_gui_frontend_services=>gui_download( EXPORTING
                                              filename = 'c:\temp\test.xml'
                                              filetype = 'BIN'
                                              bin_filesize = lv_size
                                            CHANGING
                                              data_tab = it_xml_out ).
  ENDIF.

Variante 3 (Applikationsserver)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).
  
  ...
  
* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* Stream für Ausgabe in Datei '/tmp/test/test.xml' auf dem Applikationsserver
  DATA(o_stream) = o_sf->create_ostream_uri( system_id = '/tmp/test/test.xml' ).
  o_stream->set_encoding( encoding = o_encoding ).
  o_stream->set_pretty_print( pretty_print = abap_true ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

* XML-String in Datei auf Applikationsserver generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
    ...
  ENDIF.

[ABAP] XML-Dokument aufbauen / erstellen und rendern

TRY.
* Interface
    DATA(o_ixml) = cl_ixml=>create( ).

* Document
    DATA(o_doc) = o_ixml->create_document( ).

* Root definieren
    DATA(o_root) = o_doc->create_simple_element_ns( prefix = 'asx'
                                                    name = 'list'
                                                    parent = o_doc ).

* zwei Root-Element-Attribute hinzufügen
    o_root->set_attribute_ns( name =  'asx'
                              prefix = 'xmlns'
                              value = 'http://www.google.com/xml' ).

    o_root->set_attribute_ns( name =  'version'
                              value = '1.0' ).

* Node1 unterhalb Root definieren
    DATA(o_node1) = o_doc->create_simple_element_ns( prefix = 'asx'
                                                     name = 'names'
                                                     parent = o_root ).

* Node2 zur Node1 hinzufügen
    DATA(o_node2) = o_doc->create_simple_element_ns( name = 'name'
                                                     value = 'ABC'
                                                     parent = o_node1  ).

* XML-String generieren
    DATA: xml TYPE string.

    DATA(o_stream) = o_ixml->create_stream_factory( )->create_ostream_cstring( xml ).
    o_ixml->create_renderer( document = o_doc
                             ostream = o_stream )->render( ).

* Anzeige im Browser
    cl_abap_browser=>show_xml( xml_string = xml
                               title      = 'Test XML'
                               size       = cl_abap_browser=>large ).

  CATCH cx_root INTO DATA(e_text).
    WRITE: / e_text->get_text( ).
ENDTRY.