Tratando de Grandes Mensagens XML

Quando um fluxo de bits de entrada é analisado e é criada uma árvore lógica, a representação da árvore de uma mensagem do XML é geralmente maior e, em alguns casos, muito maiores, que o fluxo de bits correspondente. As causas disso incluem:
  • A inclusão de ponteiros que vinculam os objetos em conjunto
  • A conversão de dados de caracteres em Unicode; isso pode duplicar o tamanho
  • A inclusão de nomes de campos que podem ter sido implícitos no fluxo de bits
  • A presença de dados de controle associados à operação do intermediário

A manipulação de uma árvore de mensagens grande pode exigir uma grande quantidade de armazenamento. Se você desenvolver um fluxo de mensagens que manipule mensagens grandes compostas de estruturas de repetição, poderá codificar instruções ESQL, que ajudam a reduzir a carga de armazenamento no intermediário. Essas instruções suportam o acesso aleatório e seqüencial à mensagem, mas supõem que você não necessite de acesso à mensagem completa de uma vez.

Essas instruções ESQL fazem com que o intermediário execute a análise limitada da mensagem e mantenha somente a parte da árvore de mensagens que reflita um único registro no armazenamento por vez. Se seu processamento solicitar que você retenha informações de registro a registro (por exemplo, para calcular um preço total de uma estrutura de repetição de itens em uma seqüência), você pode declarar, inicializar e manter variáveis ESQL ou pode salvar os valores em outra parte da árvore de mensagens, por exemplo, Ambiente Local.

Essa técnica reduz a memória utilizada pelo intermediário para a memória necessária para manter os fluxos de bits de entrada e de saída completos mais a memória necessária para árvores de apenas um registro e fornece economia de memória, mesmo quando um número pequeno de repetições for encontrado na mensagem. O intermediário utiliza a análise parcial e a capacidade de analisar partes específicas da árvore de mensagens na parte correspondente do fluxo de bits.

Para utilizar essas técnicas no nó Compute, aplique estas técnicas gerais:
  • Copie o corpo da mensagem de entrada como um fluxo de bits em uma pasta especial na mensagem de saída. Isso cria uma cópia modificável da mensagem de entrada que não é analisada e que portanto utiliza uma quantidade mínima de memória.
  • Evite a inspeção da mensagem de entrada. Isso evita a necessidade de analisar a mensagem.
  • Utilize um loop e uma variável de referência para percorrer a mensagem, um registro de cada vez. Para cada registro:
    • Utilize transformações normais para construir uma subárvore de saída correspondente em uma segunda pasta especial.
    • Utilize a função ASBITSTREAM para gerar um fluxo de bits para a subárvore de saída armazenada em um elemento BitStream colocado na posição na árvore que corresponde a sua posição obrigatória no fluxo de bits final.
    • Utilize a instrução DELETE para excluir as árvores de mensagens de registro de entrada e saída atuais quando concluir a sua manipulação.
    • Ao concluir o processamento de todos os registros, desacople as pastas especiais para que não apareçam no fluxo de bits de saída.
Você pode variar essas técnicas para adequar o processamento necessário para suas mensagens. O ESQL abaixo fornece um exemplo de uma implementação e é uma regravação do exemplo de ESQL em Transformando uma Mensagem XML Complexa. Ele utiliza uma única instrução SET com funções SELECT aninhadas para transformar uma mensagem que contém estruturas aninhadas de repetição.
-- Copiar o cabeçalho MQMD
  SET OutputRoot.MQMD = InputRoot.MQMD;

    -- Criar uma pasta especial na mensagem de saída para receber a
árvore de entrada
    -- Obs.: SourceMessageTree é o elemento raiz de um analisador XML
    CREATE LASTCHILD OF OutputRoot.XML.Data DOMAIN 'XML' NAME
'SourceMessageTree';

    -- Copiar a mensagem de entrada em uma pasta especial na mensagem
de saída
    -- Obs.: Esta é uma raiz para cópia de raiz que, portanto, não
construirá árvores
    SET OutputRoot.XML.Data.SourceMessageTree = InputRoot.XML;

    -- Criar uma pasta especial na mensagem de saída para receber a
árvore de saída
    CREATE FIELD OutputRoot.XML.Data.TargetMessageTree;

    -- Preparar-se para examinar os itens adquiridos
    DECLARE sourceCursor REFERENCE TO
OutputRoot.XML.Data.SourceMessageTree.Invoice;
    DECLARE targetCursor REFERENCE TO
OutputRoot.XML.Data.TargetMessageTree;
    DECLARE resultCursor REFERENCE TO OutputRoot.XML.Data;
    DECLARE grandTotal   FLOAT     0.0e0;

    -- Criar um bloco para que seja fácil sair do processamento
    ProcessInvoice: BEGIN
        -- Se não houver faturas na mensagem de entrada, não há nada a
fazer
          IF NOT LASTMOVE(sourceCursor) THEN
            LEAVE ProcessInvoice;
    END IF;

        -- Examinar as faturas na árvore de origem
        InvoiceLoop : LOOP
            -- Inspecionar a fatura atual e criar uma Instrução
correspondente
            SET targetCursor.Statement =
                THE (
          SELECT                        'Mensal'                                    AS
(XML.Attribute)Type,
                        'Completo'                                       AS
(0x03000000)Style[1],
                        I.Customer.FirstName                         AS
Customer.Name,
                        I.Customer.LastName                          AS
Customer.Surname,
                        I.Customer.Title                             AS
Customer.Title,
            (SELECT
                            FIELDVALUE(II.Title)              AS Title,
                                  CAST(II.UnitPrice AS FLOAT) * 1.6 AS Cost,
                  II.Quantity                   AS Qty
                         FROM I.Purchases.Item[] AS II
                         WHERE  II.UnitPrice > 0.0              )        AS Purchases.Article[],
            (SELECT
                            SUM( CAST(II.UnitPrice AS FLOAT) *
                                   CAST(II.Quantity AS FLOAT) *
                                   1.6                          )
                         FROM I.Purchases.Item[] AS II        )            AS Amount,
                   'Dollars'                                   AS
Amount.(XML.Attribute)Currency
                    FROM sourceCursor AS I
          WHERE I.Customer.LastName <> 'White'
        );

            -- Transformar a Instrução atual em um fluxo de bits
      DECLARE StatementBitStream BLOB        
CAST(ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream) AS
BLOB);
                
            -- Se SELECT produziu um resultado (ou seja, não foi filtrado
pela cláusula WHERE),
            -- processe a Instrução
            IF StatementBitStream IS NOT NULL THEN
                -- criar um campo para conter o fluxo de bits na árvore de
resultados
        CREATE LASTCHILD OF resultCursor
           Type XML.BitStream
           NAME 'StatementBitStream'
                    VALUE StatementBitStream;

                -- Incluir a Quantidade da Instrução atual ao total geral
                -- Observar que a conversão é necessária por causa do
comportamento do elemento da sintaxe XML
                SET grandTotal = grandTotal +
CAST(targetCursor.Statement.Amount AS FLOAT);
      END IF;

            -- Excluir a árvore Instrução real deixando apenas a versão do
fluxo de bits
            DELETE FIELD targetCursor.Statement;

            -- Ir para a próxima fatura, removendo a anterior e todos os
            -- elementos de texto que possam ter sido intercalados com as
Faturas
      REPEAT                MOVE sourceCursor NEXTSIBLING;
                DELETE PREVIOUSSIBLING OF sourceCursor;
            UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR
(LASTMOVE(sourceCursor) = FALSE)
        END REPEAT;

            -- Se não houver mais faturas para processar, abandonar o loop
            IF NOT LASTMOVE(sourceCursor) THEN
                LEAVE InvoiceLoop;
      END IF;

        END LOOP InvoiceLoop;
    END ProcessInvoice;

    -- Remover as pastas temporárias de origem e destino
    DELETE FIELD OutputRoot.XML.Data.SourceMessageTree;
    DELETE FIELD OutputRoot.XML.Data.TargetMessageTree;

    -- Enfim, incluir o total geral
    SET resultCursor.GrandTotal = grandTotal;
Isso produz a seguinte mensagem de saída:
<Dados>
 <Statement Type="Monthly" Style="Full">
       <Customer>
   <Name>Andrew</Name>
               <Surname>Smith</Surname>
   		<Title>Mr</Title>
       </Customer>
       <Purchases>
          <Article>
    <Title>The XML Companion </Title>
        <Cost>4.472E+1</Cost>
             <Qty>2</Qty>
        </Article>
          <Article>
    <Title>A Complete Guide to DB2 Universal Database</Title>
        <Cost>6.872E+1</Cost>
             <Qty>1</Qty>
        </Article>
          <Article>
    <Title>JAVA 2 Developers Handbook</Title>
        <Cost>9.5984E+1</Cost>
             <Qty>1</Qty>
        </Article>
       </Purchases>
  <Amount Currency="Dollars">2.54144E+2</Amount>
    </Statement>
 <GrandTotal>2.54144E+2</GrandTotal>
</Data>
Conceitos relacionados
Visão Geral de Fluxos de Mensagens
Visão Geral do ESQL
Tarefas relacionadas
Projetando um Fluxo de Mensagens
Definindo o Conteúdo do Fluxo de Mensagens
Gerenciando Arquivos ESQL
Transformando uma Mensagem XML Complexa
Referências relacionadas
Nó Compute
Instrução DELETE
função ASBITSTREAM
Mensagem de Exemplo
Avisos | Marcas Registradas | Downloads | Biblioteca | Suporte | Feedback
Direitos Autorais IBM Corporation 1999, 2006 Última Atualização: 1 Sep 2006
ac16740_