Pular para o conteúdo

Varrendo o XPath e seus valores no XML usando PL/SQL

XPath e seus valores no XML usando PL/SQL

Olá camaradas !

Me perguntaram como varrer um XML, exibir todos os XPaths e mostrar os seus respectivos valores. Isso após ler esse mesmo XML de um campo na tabela.

Isso não é algo de outro mundo, mas percebi que muitos não sabiam exatamente como fazer isso. Então decidi escrever um pequeno tutorial de como conseguir esse feito. 🙂

Primeiramente, vamos criar a nossa tabela:

CREATE TABLE tab_xml (
  nf  SYS.XMLTYPE
);

Table TAB_XML created.

Para testar, precisaremos de um XML. Existe uma maneira simples de gerarmos um, que é fazer um SELECT em uma tabela utilizando o hint /*xml*/.

Usarei uma tabela qualquer nesse teste.

SELECT /*xml*/ periodo,id_source,id,flexfield2,flexfield4
FROM  <tabela>
WHERE periodo = '04/2014'

O resultado é:

<?xml version="1.0"  encoding="UTF-8" ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="PERIODO"><![CDATA[04/2014]]></COLUMN>
		<COLUMN NAME="ID_SOURCE"><![CDATA[100]]></COLUMN>
		<COLUMN NAME="ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="FLEXFIELD2"><![CDATA[202168]]></COLUMN>
		<COLUMN NAME="FLEXFIELD4"><![CDATA[30/04/2014]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="PERIODO"><![CDATA[04/2014]]></COLUMN>
		<COLUMN NAME="ID_SOURCE"><![CDATA[100]]></COLUMN>
		<COLUMN NAME="ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="FLEXFIELD2"><![CDATA[202167]]></COLUMN>
		<COLUMN NAME="FLEXFIELD4"><![CDATA[30/04/2014]]></COLUMN>
	</ROW>
</RESULTS>

Se quiser saber mais sobre esse tipo de hint, leia o meu artigo abaixo:

https://www.profissionaloracle.com.br/2016/11/17/exportando-dados-no-sql-developer/

Agora que temos o nosso XML, vamos inserí-lo na tabela que criamos:

DECLARE
  v_xml   SYS.XMLTYPE;
  v_doc   CLOB;
BEGIN
  -- XMLTYPE created from a CLOB
  v_doc := '<?xml version="1.0"  encoding="UTF-8" ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="PERIODO"><![CDATA[04/2014]]></COLUMN>
		<COLUMN NAME="ID_SOURCE"><![CDATA[100]]></COLUMN>
		<COLUMN NAME="ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="FLEXFIELD2"><![CDATA[202168]]></COLUMN>
		<COLUMN NAME="FLEXFIELD4"><![CDATA[30/04/2014]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="PERIODO"><![CDATA[04/2014]]></COLUMN>
		<COLUMN NAME="ID_SOURCE"><![CDATA[100]]></COLUMN>
		<COLUMN NAME="ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="FLEXFIELD2"><![CDATA[202167]]></COLUMN>
		<COLUMN NAME="FLEXFIELD4"><![CDATA[30/04/2014]]></COLUMN>
	</ROW>
</RESULTS>';

  v_xml := SYS.XMLTYPE.createXML(v_doc);

  INSERT INTO tab_xml(nf) VALUES (v_xml);

  COMMIT;
END;
/

PL/SQL procedure successfully completed.

Ótimo ! Agora vamos a parte divertida. Vamos rodar o nosso script para destrinchar o XPath e seus valores:

WITH params AS 
   (
    SELECT nf p_xml
    FROM   tab_xml  
)    
SELECT element_path
      ,element_text
FROM  XMLTable
        (
         '              
          for $i in $doc/descendant-or-self::*
          return <element>
                 <element_path> {$i/string-join(ancestor-or-self::*/name(.), ''/'')} </element_path>
                 <element_content> {$i/text()}</element_content>
               </element>  
         '
         PASSING 
            (
             SELECT p_xml 
             FROM params
             ) AS "doc"
         COLUMNS 
            element_path   varchar2(4000) path '//element_path',
            element_text   varchar2(4000) path '//element_content'
         )

E o resultado é:

image 25

Todos os XPath e seus valores foram listados !

Creio que não escolhi o melhor modelo de XML, para demonstrar o resultado. Então vamos mudar um pouquinho ele:

<?xml version="1.0"  encoding="UTF-8" ?>
<RESULTS>
	<ROW>
		<PERIODO><![CDATA[04/2014]]></PERIODO>
		<ID_SOURCE><![CDATA[100]]></ID_SOURCE>
		<ID><![CDATA[1]]></ID>
		<FLEXFIELD2><![CDATA[202168]]></FLEXFIELD2>
		<FLEXFIELD4><![CDATA[30/04/2014]]></FLEXFIELD4>
	</ROW>
	<ROW>
		<PERIODO><![CDATA[05/2014]]></PERIODO>
		<ID_SOURCE><![CDATA[200]]></ID_SOURCE>
		<ID><![CDATA[1]]></ID>
		<FLEXFIELD2><![CDATA[202170]]></FLEXFIELD2>
		<FLEXFIELD4><![CDATA[30/05/2014]]></FLEXFIELD4>
	</ROW>
</RESULTS>

Agora vamos limpar a nossa tabela:

DELETE FROM tab_xml
/

1 row deleted.

Ótimo ! Agora vamos inserir o nosso novo XML:

DECLARE
  v_xml   SYS.XMLTYPE;
  v_doc   CLOB;
BEGIN
  -- XMLTYPE created from a CLOB
  v_doc := '<?xml version="1.0"  encoding="UTF-8" ?>
<RESULTS>
	<ROW>
		<PERIODO><![CDATA[04/2014]]></PERIODO>
		<ID_SOURCE><![CDATA[100]]></ID_SOURCE>
		<ID><![CDATA[1]]></ID>
		<FLEXFIELD2><![CDATA[202168]]></FLEXFIELD2>
		<FLEXFIELD4><![CDATA[30/04/2014]]></FLEXFIELD4>
	</ROW>
	<ROW>
		<PERIODO><![CDATA[05/2014]]></PERIODO>
		<ID_SOURCE><![CDATA[200]]></ID_SOURCE>
		<ID><![CDATA[1]]></ID>
		<FLEXFIELD2><![CDATA[202170]]></FLEXFIELD2>
		<FLEXFIELD4><![CDATA[30/05/2014]]></FLEXFIELD4>
	</ROW>
</RESULTS>';

  v_xml := SYS.XMLTYPE.createXML(v_doc);

  INSERT INTO tab_xml(nf) VALUES (v_xml);

  COMMIT;
END;
/

PL/SQL procedure successfully completed.

Executando novamente o nosso script:

WITH params AS 
   (
    SELECT nf p_xml
    FROM   tab_xml  
)    
SELECT element_path
      ,element_text
FROM  XMLTable
        (
         '              
          for $i in $doc/descendant-or-self::*
          return <element>
                 <element_path> {$i/string-join(ancestor-or-self::*/name(.), ''/'')} </element_path>
                 <element_content> {$i/text()}</element_content>
               </element>  
         '
         PASSING 
            (
             SELECT p_xml 
             FROM params
             ) AS "doc"
         COLUMNS 
            element_path   varchar2(4000) path '//element_path',
            element_text   varchar2(4000) path '//element_content'
         )
image 26

Creio que visualmente, ficou melhor para entender o resultado ! 🙂

Tenho certeza de que pensou algo do tipo “Legal, era o resultado que eu precisava, mas que código é esse ?!?“.

Principalmente nessa parte:

for $i in $doc/descendant-or-self::*
          return <element>
                 <element_path> {$i/string-join(ancestor-or-self::*/name(.), ''/'')} </element_path>
                 <element_content> {$i/text()}</element_content>
               </element>  

Essa parte é em XQuery ! Mas o que é XQuery ?

XQuery é uma linguagem de consulta, com alguns recursos de programação, que é projetada para fazer consultas em coleções de dados em XML. Ela é semanticamente similar ao SQL. (Obrigado Wikipédia !)

Com o XQuery, é possível extrair praticamente qualquer tipo de informação de um XML. Além de ser extremamente rápido !

Utilizando XQuery, já consegui decompor arquivos XMLs enormes com milhares de itens, em questão de segundos !

Se você quiser se aprofundar mais em XQuery, deixarei os links nas referências abaixo !

Um grande abraço !

Referências

Sergio Willians

Sergio Willians

Sergio Willians é o fundador do GPO (Grupo de Profissionais Oracle) e possui quase 30 anos de experiência em tecnologias Oracle, sendo especialista em desenvolvimento Forms/Reports, PL/SQL e EBS (E-Business Suite) nos módulos Receivables, Payables e General Ledger. Atualmente trabalha na Scania Latin America, onde se dedica à área de integração de dados com Confluent Kafka. Sua paixão é compartilhar conhecimento com a comunidade Oracle, contribuindo para o crescimento e a excelência da plataforma.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress