XML メッセージのツリー表記は通常、入力ビット・ストリームより大きくなります。 大規模なメッセージ・ツリーの操作には多くのストレージが必要ですが、ESQL ステートメントをコーディングすれば、ブローカーのストレージ・ロードを軽減することができます。
大規模なメッセージ・ツリーの操作には多くのストレージが必要です。 繰り返し構造からなる大きなメッセージを扱うメッセージ・フローを設計するとき、ESQL ステートメントをコーディングすれば、 ブローカーのストレージ・ロードを軽減することができます。 このステートメントはメッセージへのランダム・アクセスと順次アクセスの両方をサポートしますが、一度にメッセージ全体にアクセスする必要がないことを想定します。
このような ESQL ステートメントによって、 ブローカーはメッセージを限定的に構文解析して、単一レコードを表すメッセージ・ツリーのその部分だけを一度にストレージ内に保持します。 処理で 1 つのレコードから次のレコードに移るときに情報を保持しなければならない場合 (例えば、注文に含まれる各品目の繰り返し構造から合計価格を計算する場合)、いくつかの ESQL 変数を宣言し、初期化して保持することができます。あるいは、メッセージ・ツリー内の他の場所 (例えばローカル環境内) に値を保存する方法もあります。
この技法によって、ブローカーによるメモリーの使用量が減少し、入出力ビット・ストリームの全体と、ただ 1 つのレコードのメッセージ・ツリーを保持するために必要な容量だけが必要になります。 この技法を使えば、メッセージ内での繰り返し回数が少ない場合でもメモリーが節約されます。 ブローカーは限定的に構文解析するだけでよく、 メッセージ・ツリー内の指定された部分だけをビット・ストリームの対応する部分との間で解析します。
実際のメッセージ処理の必要に合わせて、 上記の手法を独自に変えることもできます。
-- Copy the MQMD header
SET OutputRoot.MQMD = InputRoot.MQMD;
-- Create a special folder in the output message to hold the input tree
-- Note : SourceMessageTree is the root element of an XML parser
CREATE LASTCHILD OF OutputRoot.XMLNS.Data DOMAIN 'XMLNS' NAME 'SourceMessageTree';
-- Copy the input message to a special folder in the output message
-- Note : This is a root to root copy which will therefore not build trees
SET OutputRoot.XMLNS.Data.SourceMessageTree = InputRoot.XMLNS;
-- Create a special folder in the output message to hold the output tree
CREATE FIELD OutputRoot.XMLNS.Data.TargetMessageTree;
-- Prepare to loop through the purchased items
DECLARE sourceCursor REFERENCE TO OutputRoot.XMLNS.Data.SourceMessageTree.Invoice;
DECLARE targetCursor REFERENCE TO OutputRoot.XMLNS.Data.TargetMessageTree;
DECLARE resultCursor REFERENCE TO OutputRoot.XMLNS.Data;
DECLARE grandTotal FLOAT 0.0e0;
-- Create a block so that it's easy to abandon processing
ProcessInvoice: BEGIN
-- If there are no Invoices in the input message, there is nothing to do
IF NOT LASTMOVE(sourceCursor) THEN
LEAVE ProcessInvoice;
END IF;
-- Loop through the invoices in the source tree
InvoiceLoop : LOOP
-- Inspect the current invoice and create a matching Statement
SET targetCursor.Statement = THE (SELECT 'Monthly' AS (XML.Attribute)Type,
'Full' 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');
-- Turn the current Statement into a bit stream
DECLARE StatementBitStream BLOB
ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream);
-- If the SELECT produced a result
-- (that is, it was not filtered out by the WHERE clause),
-- process the Statement
IF StatementBitStream IS NOT NULL THEN
-- create a field to hold the bit stream in the result tree
CREATE LASTCHILD OF resultCursor
Type XML.BitStream
NAME 'StatementBitStream'
VALUE StatementBitStream;
-- Add the current Statement's Amount to the grand total
-- Note that the cast is necessary because of the behavior
-- of the XML syntax element
SET grandTotal = grandTotal
+ CAST(targetCursor.Statement.Amount AS FLOAT);
END IF;
-- Delete the real Statement tree leaving only the bit stream version
DELETE FIELD targetCursor.Statement;
-- Step onto the next Invoice,
-- removing the previous invoice and any
-- text elements that might have been
-- interspersed with the Invoices
REPEAT
MOVE sourceCursor NEXTSIBLING;
DELETE PREVIOUSSIBLING OF sourceCursor;
UNTIL (FIELDNAME(sourceCursor) = 'Invoice')
OR (LASTMOVE(sourceCursor) = FALSE)
END REPEAT;
-- If there are no more invoices to process, abandon the loop
IF NOT LASTMOVE(sourceCursor) THEN
LEAVE InvoiceLoop;
END IF;
END LOOP InvoiceLoop;
END ProcessInvoice;
-- Remove the temporary source and target folders
DELETE FIELD OutputRoot.XMLNS.Data.SourceMessageTree;
DELETE FIELD OutputRoot.XMLNS.Data.TargetMessageTree;
-- Finally add the grand total
SET resultCursor.GrandTotal = grandTotal;
<Data>
<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>