Práce s XML v ABAPu - 3. část

SAP logo

Tímto článkem bych rád zakončil můj krátký seriál (1. část, 2. část) o programování XML v ABAPu. Závěrečná část se bude zabývat parsováním XML souborů s využitím iXML knihovny.

Jak na XML parser

Jak již bylo řečeno v předchozí části, ke XML dokumentu lze přistupovat dvojím způsobem:

  1. Přes rozhraní řízené událostmi
  2. Přes DOM model

Já bych se chtěl zaměřit na druhou variantu, tedy zpracovaní XML dokumentu, které využívá standard XML DOM 1.0.

iXML knihovnu umíme připojit už z minula, takže jen pro úplnost:

type-pools: ixml.
class cl_ixml definition load.

Opět budeme muset vytvořit instance starých známých objektů iXML factory a stream factory. Dále je třeba načíst XML soubor do interní tabulky pomocí rutiny get_xml_table (podrobně si ji můžete prostudovat ve vzorovém programu), vytvořit proud g_istream reprezentující vstupní soubor a vytvořit DOM model dokumentu.

DATA: g_ixml            TYPE REF TO if_ixml,
      g_streamfactory   TYPE REF TO if_ixml_stream_factory,
      g_parser          TYPE REF TO if_ixml_parser,
      g_istream         TYPE REF TO if_ixml_istream,
      g_document        TYPE REF TO if_ixml_document,
      g_node            TYPE REF TO if_ixml_node,
      g_xmldata         TYPE string,  
      g_error           TYPE xfeld.    
      
DATA: g_xml_table       TYPE TABLE OF t_xml_line,
      g_xml_line        TYPE t_xml_line,
      g_xml_table_size  TYPE i.      

* Creating a ixml factory
g_ixml = cl_ixml=>create( ).
* Creating the dom object model
g_document = g_ixml->create_document( ).
* Creating a stream factory
g_streamfactory = g_ixml->create_stream_factory( ).
* upload XML document from file 
PERFORM get_xml_table CHANGING g_xml_table_size g_xml_table. 
* wrap the table containing the file into a stream
g_istream = g_streamfactory->create_istream_itable(
                              table = g_xml_table
                              size  = g_xml_table_size ).
* Creating a document
g_document = g_ixml->create_document( ).                                                 

A nýní se již dostáváme k samotnému parsování dokumentu pomocí rutiny parse_document:

* Parse document
PERFORM parse_document.
CHECK g_error = space.

*---------------------------------------------------------------------*
*       FORM parse_document                                           *
*---------------------------------------------------------------------*
FORM parse_document.
  DATA: parseerror TYPE REF TO if_ixml_parse_error,
        str        TYPE string,
        i          TYPE i,
        count      TYPE i,
        index      TYPE i.

*   Create a Parser
  g_parser = g_ixml->create_parser( stream_factory = g_streamfactory
                                    istream        = g_istream
                                    document       = g_document ).
*   Parse the stream
  IF g_parser->parse( ) NE 0.
    g_error = 'X'.
    IF g_parser->num_errors( ) NE 0.
      count = g_parser->num_errors( ).
      ULINE.
      WRITE: count, ' parse errors have occured:'.
      index = 0.
      WHILE index < count.
        parseerror = g_parser->get_error( index = index ).
        i = parseerror->get_line( ).
        WRITE: 'line: ', i.
        i = parseerror->get_column( ).
        WRITE: 'column: ', i.
        str = parseerror->get_reason( ).
        WRITE: str.
        index = index + 1.
      ENDWHILE.
    ENDIF.
  ENDIF.
ENDFORM.                                                 

Na závěr vykonáme průchod výsledným DOM modelem a výpis XML stromu na obrazovku pomocí rutiny process_dom:

* Process the document
IF g_parser->is_dom_generating( ) EQ 'X'.
  PERFORM process_dom USING g_document.
ENDIF.

*---------------------------------------------------------------------*
*       FORM process_dom                                              *
*---------------------------------------------------------------------*
FORM process_dom USING document TYPE REF TO if_ixml_document.
  DATA: node      TYPE REF TO if_ixml_node,
        iterator  TYPE REF TO if_ixml_node_iterator,
        nodemap   TYPE REF TO if_ixml_named_node_map,
        attr      TYPE REF TO if_ixml_node,
        name      TYPE string,
        prefix    TYPE string,
        value     TYPE string,
        indent    TYPE i,
        count     TYPE i,
        index     TYPE i.

  node ?= document.
  CHECK NOT node IS INITIAL.

  ULINE.
  WRITE: /.
  WRITE: /' DOM-TREE'.
  WRITE: /.
  IF node IS INITIAL. EXIT. ENDIF.
*   create a node iterator
  iterator  = node->create_iterator( ).
*   get current node
  node = iterator->get_next( ).

*   loop over all nodes
  WHILE NOT node IS INITIAL.
    indent = node->get_height( ) * 2.
    indent = indent + 20.

    CASE node->get_type( ).
      WHEN if_ixml_node=>co_node_element.
*         element node
        name    = node->get_name( ).
        nodemap = node->get_attributes( ).
        WRITE: / 'ELEMENT  :'.
        WRITE: AT indent name COLOR COL_POSITIVE INVERSE.
        IF NOT nodemap IS INITIAL.
*           attributes
          count = nodemap->get_length( ).
          DO count TIMES.
            index  = sy-index - 1.
            attr   = nodemap->get_item( index ).
            name   = attr->get_name( ).
*              prefix = attr->get_namespace_prefix( ).
            value  = attr->get_value( ).
            WRITE: / 'ATTRIBUTE:'.
            WRITE: AT indent name  COLOR COL_HEADING INVERSE, '=',
                             value COLOR COL_TOTAL   INVERSE.
          ENDDO.
        ENDIF.
      WHEN if_ixml_node=>co_node_text OR
           if_ixml_node=>co_node_cdata_section.
*         text node
        value  = node->get_value( ).
        WRITE: / 'VALUE    :'.
        WRITE: AT indent value COLOR COL_GROUP INVERSE.
    ENDCASE.
*     advance to next node
    node = iterator->get_next( ).
  ENDWHILE.
ENDFORM.                                              

Vzorový program si můžete prohlédnout zde.

Související



Podělte se o tento článek s ostatními… Sdílet

Komentáře

avatar

[1] Ondřej

clock  19. 12. 2009, 23:45

A ještě zde můžeš doplnit možnost zpracování XML dokumentů skrze XSL transformace (XSLT programy – CALL TRANSFORMATION).
Hrál jsem si s tím v roce 2004, když to byla novinka na verzi 4.7 (6.20) a vyřešil tím například dynamické generování field-catalogu pro ALV GRID (transformace ABAP->ABAP) ..přiznávám, že je to samozřejmě v tomto případě docela nepraktický úlet 


avatar

[2] Adam Michnik

clock  09. 01. 2010, 16:43

Pěkný článek a i celkově máte hodně zajímavé stránky. Jen tak dál. Dobře se to čte a je to inteligentní – to se často na internetu nevidí.


Pavel

[3] Pavel

clock  10. 01. 2010, 10:18

Reakce na [2] > No děkuji pěkně. Takový povzbudivý komentář jednomu zalichotí, že by měl skoro chuť napsat po dlouhé době další článek. 


avatar

[4] Martin Šebesta

clock  20. 11. 2012, 15:07

Diky za inspiraci, moc hezky zpracovane. Teď už se jen rozhodnout, jestli jit přes ixml nebo transformaci
Podobně zpracovaný návod bych určitě ne jen já uvítal i na xml transformace.


Pavel

[5] Pavel

clock  20. 11. 2012, 15:24

Reakce na [4] > Být vámi zvolil bych raději XML transformace (STRANS). V poslední době jsem s nimi pracoval poměrně hodně a vše funguje parádně. Na návody bohužel nějak nezbývá čas…



Přidat komentář

Upozornění: Komentář musí být před publikováním schválen!
: *
: *

: *

:



  • Pole označená hvězdičkou jsou povinná.
  • Můžete použít Texy! syntaxi. HTML tagy nejsou povolené!
    Příklad syntaxe: **tučně**, *kurzíva*.
  • Odkazy začínající http(s)://, ftp:// a mailto: se zformátují automaticky.
  • Na jiné komentáře se můžete odkazovat např. zápisem [1].
  • Gravatar připojený k Vaší e-mailové bude zobrazen u komentáře.
  • Upozorňuji, že komentáře, které se netýkají tématu článku, jsou vulgární nebo urážlivé, mohou být smazány.

Začátek článku Nahoru | Začátek komentářů Nahoru

© Pavel Jaroš [Sektor PJ] · Nahoru Nahoru