On 20/02/2014 12:38, Matheus de Oliveira wrote:
Renato, sério cara, não faça top-posting, veja as regras da lista:

http://www.postgresql.org.br/RegrasLista

É simples, basta editar a mensagem antes de responder, e ir respondendo embaixo da mensagem anterior, como vou fazer a seguir:


2014-02-20 11:24 GMT-03:00 Renato Poleti <ren...@poleti.com.br <mailto:ren...@poleti.com.br>>:

    Matheus, eu verifiquei estas funções, mas não conseguir chegar a
    uma solução de looping no XML.
    Imagina que tenha uma function que recebe como parâmetro o
    seguinte XML

    <?xml version="1.0? encoding="UTF-8??>
    <items>
        <item>
            <name color="brown">Chair</name>
            <price>$53</price>
        </item>
        <item>
            <name color="red">Table Lamp</name>
            <price>$10</price>
        </item>
    </items>

    Preciso saber:
    a) Quantos itens eu tem.
    b) Pegar cada item e fazer um insert em determina tabela (o
    problema está no looping)

    Lembrando que pode vir 1 item, como varios itens.


Agora sim, posso ajudar melhor... Vamos assumir que tenhas uma função assim:

CREATE FUNCTION process_item(data xml)
    RETURNS TABLE(name text, color text, price text)
    ...

E ela pega o dado passado via parâmetro e retorna uma linha para cada item, retornando name, color e price.

O corpo dessa função é bem simples nesse caso. Na verdade nem precisava de uma função, bastava a seguinte query (que seria também o corpo da função em linguagem SQL):

SELECT
        (xpath('/item/name[1]/text()', item))[1]::text AS name,
        (xpath('/item/name[1]/@color', item))[1]::text AS color,
        (xpath('/item/price[1]/text()', item))[1]::text AS price
    FROM unnest(xpath('/items/item', data)) t(item);

A dica ajudou muito, dei uma lida novamente na documentação e consegui entender umas coisas. Eu fiz o exemplo abaixo, e tenho varias tabelas desta forma, todas com "id e value" e em outro xml (outra tabela) com outros nodes, porem ai para cada xml teria que fazer cada node na mão;
a) existe alguma outra forma automática de mesclagem
b) tem como melhorar o exemplo abaixo?
c) Vejam que o "name" saiu 2x e não gostaria

Exemplo
SELECT
    xmlelement(name items,
        xmlagg(
                xmlelement(name item,
                    xmlforest (
                        (xpath('/item/id/text()', item))[1]::text AS id,
xmlelement(name name, xmlattributes((xpath('/item/name/@color', item))[1]::text as color), (xpath('/item/name/text()', item))[1]::text) as nome, (xpath('/item/price/text()', item))[1]::text AS price, (xpath('/item/value/text()', itemb))[1]::text AS val
                    )
                )
        )
    )
FROM unnest(xpath('/items/item', '<?xml version="1.0" encoding="UTF-8"?>
        <items>
            <item>
            <id>1</id>
            <name color="brown">Chair</name>
            <price>$53</price>
            </item>
            <item>
            <id>1</id>
            <name color="red">Table Lamp</name>
            <price>$10</price>
            </item>
            <item>
            <id>2</id>
            <name color="red">Table Lamp</name>
            <price>$10</price>
            </item>
        </items>')) as item
LEFT JOIN
    unnest(xpath('/items/item', '<?xml version="1.0" encoding="UTF-8"?>
    <items>
        <item>
        <id>1</id>
        <value>xpto</value>
        </item>
        <item>
        <id>1</id>
        <value>xpto2</value>
        </item>
        <item>
        <id>2</id>
        <value>xpto3</value>
        </item>
    </items>')) as itemb
ON (xpath('/item/id/text()', item))[1]::text = (xpath('/item/id/text()', itemb))[1]::text

SAIDA

<items>
        <item>
            <id>1</id>
            <nome>
                <name color="brown">Chair</name>
            </nome>
            <price>$53</price>
            <val>xpto2</val>
        </item>
        <item><id>1</id>
            <nome>
                <name color="brown">Chair</name>
            </nome>
            <price>$53</price>
            <val>xpto</val>
        </item>
        <item>
        ...
</items>


Com isso em mãos, você tem as suas respostas:

a) SELECT count(*) FROM process_item('seu xml');
b) SELECT count(*) FROM process_item('seu xml');

Claro que para (a) tem formas mais performáticas.

Resumindo, estude queries XPath, é a forma mágica de processar XML.

Atenciosamente,
--
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres <http://www.dextra.com.br/postgres/>



_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a