Reading a XML list into a custom XML enabled class
Hello, I tried to read a XML list from a web service into a response class by creating a custom collection subclass as described in this documentation page
Here's the XML file I am trying to read:
<Suppliers>
<Supplier>
<row>1</row>
</Supplier>
<Supplier>
<row>2</row>
</Supplier>
</Suppliers>
XMLXML
And the different classes I defined to project the XML into:
Class App.Messages.GetSuppliersResponse Extends (%Persistent, Ens.Response)
{
Property Suppliers As App.Objects.Suppliers;
Method Deserialize(stream as %Stream.Object) as %Status
{
set reader = ##class(%XML.Reader).%New()
$$$ThrowOnError(reader.OpenStream(.stream))
Do reader.CorrelateRoot($CLASSNAME(..Suppliers))
Do reader.Next(..Suppliers, .tSC)
quit tSC
}
}
Class App.Objects.Suppliers Extends (%ListOfObjects, %XML.Adaptor)
{
Parameter XMLNAME = "Suppliers";
Parameter XMLITEMNAME = "Supplier";
Parameter ELEMENTTYPE = "App.Objects.Supplier";
}
Class App.Objects.Supplier Extends (%Persistent, %XML.Adaptor)
{
Parameter XMLNAME = "Supplier";
Property row As %Integer(XMLNAME = "row");
}
ObjectScriptObjectScript
I just cannot figure out how to read a XML where the root is a list, and get the following error by calling the method Deserialize in the response class:
ERROR #6237: Unexpected tag in XML input: Supplier (ending at line 2 character 15).
Has someone ever dealt with this kind of problem?
Any help would be appreciated, thank you
Product version: IRIS 2023.3
First I'd suggest not to use a persistent class "linked" to a message (Ens.Response in this case), Supplier is linked by your message class in this case.
If you do it, you will definitely create "orphaned" persistent objects when you purge, unless you add some logic (like triggers and callbacks) to delete the "linked" persistent objects when a message is purged.
To avoid this (when possible) a serial class is preferred.
So, the Supplier class would be:
Class Community.App.Msg.Supplier Extends (%SerialObject, %XML.Adaptor) { Property row As %Integer; }
As for the message class:
Class Community.App.Msg.Suppliers Extends Ens.Response { Property Supplier As list Of Community.App.Msg.Supplier(XMLPROJECTION = "ELEMENT"); ClassMethod test() As %Status { set XmlString="<Suppliers><Supplier><row>1</row></Supplier><Supplier><row>2</row></Supplier></Suppliers>" set reader = ##class(%XML.Reader).%New() $$$ThrowOnError(reader.OpenString(XmlString)) do reader.CorrelateRoot("Community.App.Msg.Suppliers") do reader.Next(.Suppliers, .tSC) do Suppliers.XMLExport(,",indent") quit tSC } }
For simplicity I modified the sample to be a classmethod.
When the test() method is run the output is:
EPTEST>d ##class(Community.App.Msg.Suppliers).test() <Suppliers> <Supplier> <row>1</row> </Supplier> <Supplier> <row>2</row> </Supplier> </Suppliers>
The relevant documentation is "Controlling the Form of the Projection for Collection Properties" here.
Let me add a few notes.
If a class extend Ens.Response or Ens.Request is not necessary to extend %Persistent because is already inherited by Ens.Request/Ens.Response.
Edit: please see Antoine commnet below
If the desired XML tag correspond to the class name (without package), it is not necessary to add the XMLNAME parameter, like you did in App.Objects.Suppliers class.
Same goes for XMLNAME property parameter XMLNAME = "row" is not necessary because the property name correspond to the desired XML tag name.
Oh I see, what I was really missing out there was the XMLPROJECTION = "ELEMENT"
Thank you very much for your answer and clearing out some misconceptions about persistent classes
Though I have one additional note here:
From what I have read in the IRIS documentation, it is advised to also extend a message class with %Persistent as the primary subclass for performance reasons
see https://docs.intersystems.com/iris20231/csp/docbook/DocBook.UI.Page.cls?KEY=EGDV_messages#EGDV_message_body_class
Hi Antoine,
you are right regarding inheriting from %Persistent and Ens.Request/Response, it does makes sense in many cases!
I've edited my message to refer to your comment