XML-ДОМ. Получить элемент по имени на первом дочернем уровне

У меня есть такой xml:

<root>
  <element1>
     <doc>2</doc>
  </element1>
  <doc>1</doc>
</root>

Я хочу получить элемент на первом дочернем уровне после корневого элемента (значение = 1). Если я сделаю это через нодлист (версия pl/sql xmldom api):

nl := getElementsByTagName(rootnode,'doc');
len := xmldom.getLength(nl);
IF LEN>0 THEN
    N:=xmldom.item(nl, 0);
END IF;
RETURN N;

первым элементом в списке будет элемент со значением = 2. Как я могу обрабатывать только дочерние узлы первого дочернего уровня без циклического прохождения элементов?


person Andrey Khataev    schedule 03.02.2012    source источник


Ответы (2)


С DBMS_XMLDOM используйте GETCHILDRENBYTAGNAME:

declare
  xml constant xmltype := xmltype(
'<root>
  <element1>
     <doc>2 - two</doc>
  </element1>
  <doc>1 - one</doc>
</root>'
);
  doc constant dbms_xmldom.domdocument := dbms_xmldom.newdomdocument(xml);

  root_elem constant dbms_xmldom.domelement :=
    dbms_xmldom.getdocumentelement(doc);

  doc_nodes constant dbms_xmldom.domnodelist :=
    dbms_xmldom.getchildrenbytagname(root_elem, 'doc');
begin
  declare
    last_index constant pls_integer := dbms_xmldom.getlength(doc_nodes) - 1;
    node dbms_xmldom.domnode;
    text_node dbms_xmldom.domnode;
  begin
    for i in 0 .. last_index loop
      node := dbms_xmldom.item(doc_nodes, i);
      text_node := dbms_xmldom.getfirstchild(node);
      dbms_output.put_line('i = ' || i ||
                           ' name = ' || dbms_xmldom.getnodename(node) ||
                           ' type = ' || dbms_xmldom.getnodetype(node) ||
                           ' text = ' || dbms_xmldom.getnodevalue(text_node));
    end loop;
  end;
end;
/

Выход:

SQL> @so24
i = 0 name = doc type = 1 text = 1 - one

PL/SQL procedure successfully completed.

SQL>
person user272735    schedule 03.02.2012
comment
Я вижу, что вы используете LOOP, которого я просил избегать. Но я не могу понять, почему вы получаете результат на первой итерации (i = 0) - person Andrey Khataev; 05.02.2012
comment
@AndreyKhataev: Я зацикливаюсь, потому что getchildrenbytagname возвращает domnodelist - количество узлов в списке может быть любым. Если вам действительно нужен только первый узел из списка, вы можете использовать ту же технику, что и в вашем вопросе. Разница между getelementsbytagname и getchildrenbytagname заключается в том, что первый возвращает элементы на всех подуровнях (root/element1/doc и root/doc), а второй возвращает только дочерние элементы (root/doc). - person user272735; 10.02.2012

Вы можете использовать пакет xslprocessor, а затем найти нужный узел с помощью XPath:

nl := xslprocessor.selectnodes(rootnode, 'root/doc');
len := xmldom.getLength(nl);
IF LEN>0 THEN
    N:=xmldom.item(nl, 0);
END IF;
RETURN N;
person A.B.Cade    schedule 06.02.2012