Question
Peter Charbonnier · Feb 1, 2021

Correlating more than one element

The docbook chapter "Importing XML into Objects" has the following tip:

You can call the Correlate() method repeatedly to correlate more than one element, although the examples in this chapter show only one correlation.

Does anyone have a good example of multiple correlations?  I've got code running that does multiple imports of the same file while changing the correlation and it's inelegant and not really what I want.

$ZV: Cache for Windows (x86-64) 2017.1.1 (Build 111U_SU) Tue May 23 2017 13:20:26 EDT
Product version:
Caché 2017.1
00
2 0 2 51

Replies

Hi Peter, 

Correlate() simply associates the given XML element with the given ObjectScript class. %XML.Reader allows you to specify multiple element/class associations by calling Correlate() multiple times. Subsequent calls to Next() will return the objects associated with the elements you've correlated, in the order in which they are found in the file. Here is a very basic example using two classes

Here are the classes:

Class Test.A Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property AProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property AProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute");
}
Class Test.B Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property BProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property BProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
}

And our XML file:

<?xml version="1.0" encoding="UTF-8"?>
<objects>
    <A AProp1="abc" AProp2="def"></A>
    <B BProp1="123" BProp2="456"></B>
</objects>

Now we can read both objects in one pass with the following method:

ClassMethod ReadXML()
{
    set reader = ##class(%XML.Reader).%New()
    do reader.OpenFile("/tmp/test.xml")
    
    do reader.Correlate("A", "Test.A")
    do reader.Correlate("B", "Test.B")
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
}

In a more complex example, you would probably want to call Next() in a loop, and actually pay attention to the error code, but this should demonstrate the point. 

I hope this helps.