· Nov 30, 2022

Iterating HS.SDA3.Container container twice

I initialize a HS.SDA3.Container from a XML stream and I need to iterate over it twice. What is a correct way of doing it? Is it enough to adjust StreamPos/StreamOref?

The optimal solution would be to use one loop, but it's not possible to combine the processing logic.

set oSDA = ##class(HS.SDA3.Container).%New()
do oSDA.InitializeXMLParse(.tQuickStream)

while oSDA.GetNextSDA(.tType, .tPatient) {
        // processing logic A

set oSDA.StreamPos = 1
do oSDA.StreamOref.Rewind()

while oSDA.GetNextSDA(.tType, .tPatient) {
        // processing logic B
Product version: IRIS 2022.1
Discussion (4)2
Log in or sign up to continue

InitializeXMLParse does a lot of necessary things including the following:

  1. Calls Rewind() on its stream property
  2. Uses XSL "OrderSDAElements" or "OrderSDAElementsEdge" to sort the SDA objects in the container.
  3. Replace the stream property on HS.SDA3.Container  with the sorted one
  4. Call Rewind() again and initialize a StreamPos property to 1   // This is used by FillBuffer()
  5. Initialize the ..StreamBuffer with the first 3600000 bytes of the stream 

This is a lot of overhead.  Also, "do oSDA.StreamOref.Rewind()" and "oSDA.StreamPos = 1" fails to re-initialize the ..StreamBuffer.

My suggestion would be to declare a MultiDimensional property in your class:
Property %sdaclass [ MultiDimensional, Private ];

Then follwing any call to GetNextSDA, save the SDA class in the MultiDimensional:
set ..%sdaclass($increment(%sdaclass))=tPatient     // replace tPatient with variable returned by GetNextSDA 

Your second pass can simply iterate over the MultiDimensional:
set subscript=""
for {
   set subscript=$order(..%sdaclass(subscript))

    set sdaclass=..%sdaclass(subscript)

    ... processing logic B