Обход всех узлов XML-документа?

#xml #abap #dom-traversal

#xml #abap #dom-обход

Вопрос:

Я хочу пройти через все узлы if_ixml_document . какой наилучший способ сделать это?

Пожалуйста, найдите образец документа.

 <text>
    <id>
         <guid auto="false">
               432543254543
         </guid>
    </id>
     <title>
         <short_title italics="on">
                <bold language = "german">
                     "Hello"
               </bold>
        </short_title>
     </title> </text>
  

В этом документе мне нужно пройти через узлы <text>, <id>, <guid> , <title>, <short_title>, <bold> и т.д.

Заранее спасибо

С уважением, Алекс

Ответ №1:

Первый шаг — проанализировать ваш XML следующим образом. Вы, конечно, можете загрузить XML из файла в строку, но это всего лишь пример:

 data: lr_xml type ref to cl_xml_document.
data: lr_node type ref to if_ixml_node.
data: lv_xml type string.

lv_xml = '<text> <id> <guid auto="false"> 432543254543 </guid> </id> <title> <short_title italics="on"> <bold language = "german"> "Hello"</bold> </short_title> </title> </text>'.

create object lr_xml.

lr_xml->parse_string( lv_xml ).
lr_node = lr_xml->get_first_node( ).
  

Теперь у вас есть экземпляр IF_XML_NODE, который указывает на корень вашего XML-документа. Теперь вы можете использовать различные методы для обхода XML-дерева и получения из него значений, используя различные методы, такие как GET_CHILDREN, GET_ATTRIBUTES, GET_NAME и т. Д.

Это будет нормально для довольно небольших XML-документов, хотя для повышения эффективности, если вы ищете определенный набор узлов, вы можете использовать запрос XPATH.

Комментарии:

1. большое спасибо за ответ. Во-первых, я не ищу какой-либо конкретный набор узлов. Я пишу очень общий метод, например, изменение значения атрибута всех элементов при некотором условии. Из этого кода я обязательно получу корневой узел. но после этого, если я использую такие методы, как get_children , я получу только непосредственный дочерний элемент корневого узла. В примере документа я получу элементы <id> и <title>, но я не получу дочерний элемент внутри них. Я ищу метод, который может обход всех элементов в документе.

2. Правильно, это дает вам только непосредственные дочерние элементы. Что вам нужно сделать, это написать рекурсивную подпрограмму для обхода всего документа. Надеюсь, у меня скоро будет время привести вам пример.

Ответ №2:

Вы можете найти подробное руководство по XML на веб-сайте документации SAP (в случае, если ссылка не работает правильно, перейдите к Руководству разработчика NetWeaver по help.sap.com и найдите «xml library»).

Глава «iXML ABAP Objects Jumpstart» должна помочь вам быстро начать работу. В параграфе «Итерация по всему DOM-дереву» приведен следующий пример кода:

 data: iterator type ref to if_ixml_node_iterator,
      node     type ref to if_ixml_node.
iterator = document->create_iterator( ).
node = iterator->get_next( ).
while not node is initial.
  * do something with the node
  ...
  node = iterator->get_next( ).
endwhile.
  

Ответ №3:

Я надеюсь, что следующий пример может прояснить ситуацию:

  DATA: lcl_xml_doc TYPE REF TO cl_xml_document,
          lf_node TYPE REF TO if_ixml_node,
          lf_value TYPE string,
          i_xml type string,
          lf_name TYPE string,
      i_xml = 'PUT your XML HERE'.
      CREATE OBJECT lcl_xml_doc.
      IF lcl_xml_doc IS BOUND.
        IF lcl_xml_doc->parse_string( i_xml ) EQ 0.
          lf_node = lcl_xml_doc->m_document.
          IF  lf_node IS NOT INITIAL. 
            lf_iterator = lf_node->create_iterator( ).
            lf_node = lf_iterator->get_next( ).
            WHILE NOT lf_node IS INITIAL.
              lf_name = lf_node->get_name( ).
              lf_value = lf_node->get_value( ).
              IF lf_name = 'text'.
               " do something for text
               ENDIF.
              ENDIF.
              lf_node = lf_iterator->get_next( ).
            ENDWHILE.
        ENDIF.
  

Наслаждайтесь,
Александр.

Ответ №4:

Ручной обход xml подвержен ошибкам и усложняется в меняющихся средах. Возможно, вы захотите проверить, действительно ли вам нужен прямой обход кода.

С помощью преобразований (XSLT) вы можете преобразовать XML в структурированные типы ABAP. Поддерживается XPath.

Объявление, тестирование и отладка преобразований выполняются с помощью редактора преобразований, открываемого транзакцией STRANS .

XSLT доступен как тип преобразования: преобразование ABAP XSLT

В вашем коде ABAP вы просто вызовете элемент language CALL TRANSFORMATION , и после этого данные будут готовы к обработке в вашей целевой структуре: Оператор ABAP: ‘ПРЕОБРАЗОВАНИЕ ВЫЗОВА’

Ответ №5:

Вы можете использовать DocumentTraversal интерфейс, который должен быть реализован любой библиотекой DOM (у Xerces он есть):

 Document doc = ...;
NodeIterator i = ((DocumentTraversal) doc).createNodeIterator(doc, 
       NodeFilter.SHOW_ELEMENT, null, false);
Element e = null;
while ((e = (Element) i.nextNode()) != null) {
    // do stuff with element
}
  

Комментарии:

1. Вопрос помечен как вопрос ABAP, поэтому я предполагаю, что он относится к языку ABAP. Может быть, @user871912 может просто подтвердить.

2. @mydoghasworms. Предоставлено. Как оказалось, ABAP поддерживает те же интерфейсы, хотя и с немного другим синтаксисом 🙂