As Robert said, XSLT... but as he indicated too, in this case XSLT would be an overkill.

But there is also a "forgotten" function, $locate() too for such cases! This function is almost never used in DC examples. Two or three lines of code, and you have the perfect solution... but for "simple" cases only. Beware of nested tags!

SetFixedValue(str,tag,value) Public
   set i=0, t="(?i)<"_tag_">[^<]+", s=$l(tag)+2
   while $locate(str,t,i,j,v) { set $e(str,j+s-$l(v),j-1)=value, i=j+s-$l(v)+$l(value) }
   quit str

It works like a charm...

set a="<Name>..."
write $$SetFixedValue^test(a,"rollno","***")  -->  <Name>ABC</Name><RollNo>***</RollNo><Name>XYZ</Name><RollNo>***</RollNo><Name>xyz</Name><RollNo>***</RollNo>

it's easy, without AM/PM

write $tr("abcd-ef-gh ij:kl:00","abcdefghijkl",202010011000),! // ODBC-Format
write $tr("gh.ef.abcd ij:kl:00","abcdefghijkl",202010011000),! // German-Format
write $tr("ef/gh/abcd ij:kl:00","abcdefghijkl",202010011000),! // US-Format

but if you need AM/PM, then the shortest way is using $zd()/$zth() functions

set datetime=202010011000
set tmp=$tr("abcdefgh ij:kl:00","abcdefghijkl",datetime) // or using $e(...)
set tmp=$e(datetime,1,8)_" "_$e(datetime,9,10)_":"_$e(datetime,11,12)_":00" write $zdt($zdth(tmp,3),1,3)

It's simple and easy... just follow the picture (I meant, the JSON string):

                   "NOKname":"Alison Bloggs",

Now we create a dynamic Object:

set obj = {}.%FromJSON(pData)

Your pData is a JSON-Array, where the (array)elements/items are objects

 (we have just one elemment), so we can say:

set item = obj.%Get(0)

This  item object has a patient property, which is an object, so we go one step deeper

set item = obj.%Get(0)
set patient = item.patient 
set patient = obj.%Get(0).patient  // same as above

Our patient object has properties like guid,  idforename, surname, dateOfBirth and NOK

The property NOK itself is, again, an array where the array elements/items are objects.

set nok = patient.NOK
set nok = obj.%Get(0).patient.NOK // same as above

Now, we know, our property NOK is an array, so we have to take of those elements. This nok elements are objects, so we can take the properties (NOKname,

set nokItem = nok.%Get(0)
write nokItem.NOKname," ",,!

or, all in one line

write obj.%Get(0).patient.NOK.%Get(0).NOKname,!

Now all together, a small routine to print out all NOKxxxx properties:

set obj = {}.%FromJSON(pData)
for i=0:1:obj.%Size()-1 { // loop over pData items grabbing patient props
    set patient = obj.%Get(i).patient
    for j=0:1:patient.NOK.%Size()-1 { // now we loop over all NOK items
        set nok = patient.NOK.%Get(j)
        write nok.NOKname,!
        write nok.NOKrelationship,!

So I hope, you see the light at the end of the tunnel...

According to above sample data, your JSON-Data (pData) is :

- an array of one or more objects

- the object(s) have "patient", "visit" and "documentAttachments" as properties

- the "patient" property is an object and has "guid", "id", "forename", "surname", and "dateOfBirth" as properties

So, to get the "forename" property, you have to do something like:

set object = {}.%FromJSON(pData)  // create a JSON-Object from JSON string
write object.%Get(0).patient.forename  // 

or step by step

set firstArrayItem = object.%Get(0) // first array item is 0
set patient = firstArrayItem.patient // this is the patioent object
write patient.forename  // now you have the name
write patient.surname // and other properties

By the way, the "visit" property is also an array! To list all the "reason" properties, you have to write a loop:

set visit = firstArrayItem.visit  // the first visit 
for i=0:1:visit.%Size()-1 {
  write visit.%Get(i).reason,!

Your output will be:



I hope, things are now more clear? 

All ISC products (Ensemble, Cache, IRIS...) have an callin and callout interface via dll/so.  As a starting point, read this

and this

You will also need some experience in C/C++ or Delphi or in other language, where you can compile *.dll (Win) or *.so (Linux) files.

See the functions $zf(-3), $zf(-4), $zf(-5) and $zf(-6)

Create a FindLab() method in your ListLabCenter class, something like:

Method FindLab(start = 0, LabId = "", Center = "", Code = "")

{    set nc1=LabId="", nc2=Center="", nc3=Code=""

     for i=start+1:1:..Labs.Count() {

         set tmp=..Labs.GetAt(i)

         if tmp.LabId=LabId!nc1, tmp.Center=Center!nc2, tmp.Code=Code!nc3 return i


   quit 0


Then use it as follows:

write obj.FindLab(0,"A08829848","A088298480003","") to find a specific Lab


set  center=0
for  { set center = obj.FindLab(center,,"A088298480003")
       /* do something with center *./

to find all LabCenter objects where Center = "A088298480003"

I assume,  your JSON is generated by converting a dynamic object to string, i.e.: 

do obj.%ToJSON()

In elsecase, it's created manually an there you could put as many quotes as you like around the numbers.

For the first case, just make a function which converts the numbers into string, see below:

test ;test for stringify
   set a={},a.Name="John",a.Age=47,a.xx="ab:1234",a.City="Boston",a.Year=2020
   set a."Arr"=[11,22,"aa","bb"]
   set a."Obj"={"aa":"bb"}

   write a.%ToJSON(),!
   write $$stringify(a).%ToJSON(),!

   set y=x.%GetIterator()
   while y.%GetNext(.i,.v) {
     set t=x.%GetTypeOf(i)
     if t="number" { d x.%Set(i,v,"string") } elseif t="array"!(t="object") { do stringify(v) }
   quit x

The output  is then:

do ^test

It would be very helpful to know, what CCR means. knows  241 acronymes for CCR (not including such as Code Certification Rule, Code Certification Report, Customer Care Report and many more) .
If you filter for Science and Medicine (in the above site), you end up with 62 acronymes.

So what does your CCR mean?

Think about, not everybody works in the same field as you. Some people, like me, wrote countless applications for marketing, business management, trading, banking, scientific solutions and others, but never for healthcare.


The first part is easy... string, integer,... that's not the problem.

The second part, is it a date or not depends on the date format(s) you expect (or allow).

But for the first part, you can use this approach:

/// Return values
/// 0=empty, 1=string, 2=integer, 3=float/radix-10, 4=float/radix-2, 5=object
ClassMethod ValType(var) 
  if var="" quit 0
  if $isobject(var) quit 5
  quit $select($length(var)>254:1, 1:$translate($ascii($listbuild(var),2),1245678,1122334))

Of course, hardcore people would use just one line

ClassMethod ValType(var) { q $s(var="":0, $isobject(var):5, $l(var)>254:1, 1:$tr($a($lb(var),2),1245678,1122334)) }

You could try this way:

Class My.Table2 Extends %Persistent

Property Name As %String;

Property Age As %Numeric;

Property City As %String;

Property Phone As %String;

ClassMethod Test()
    // This is your Data-Object...
    set data=[]
    do data.%Push({"Name":"Joe", "Age":44, "City":"Boston", "Phone":"1-234-4567"})
    do data.%Push({"Name":"Ron", "Age":48, "City":"Dallas", "Phone":"1-234-5678"})
    do data.%Push({"Name":"Eve", "Age":40, "City":"Miami",  "Phone":"1-234-4567"})
    do data.%Push($lb("Tommy", 50, "New York", "1-345-6789"))
    do data.%Push($lb("Alexa", 35, "Portland", "1-567-8901"))

    // Now insert all the above data into your table...
    if 'data.%Size() quit
    set cnt=0, size=data.%Size()
    while $i(cnt)<=size {
        set rowData=data.%Get(cnt-1)
            INSERT INTO My.Table2 (Name,Age,City,Phone)
            VALUES (My.Table2_DataProvider(:rowData), :row(2), :row(3), :row(4))

ClassMethod DataProvider(rowData) As %String [ PublicList = row, SqlProc ]
    kill row
    if $isobject(rowData) {
        set it=rowData.%GetIterator()
        while it.%GetNext(,.val) { set row($i(row))=val } 

    } else {
        for i=1:1:$ll(rowData) { set row(i)=$lg(rowData,i) }
    quit row(1)

Storage Default
<Data name="Table2DefaultData">
<Value name="1">
<Value name="2">
<Value name="3">
<Value name="4">
<Value name="5">
} }

Create your data for insert and then

INSERT into yourtable (Prop1, Prop2, ...)

VALUES (sqlProcForTheFirstValue(), :localVarForOtherValues(2), :localVatForOtherValues(3),...)

see the above example.

Take care of the sequence of INSERT names and row(i) values.

Sorry, but it's not clear to me what you want to achieve.

If you want to provide data if somebody connected to your server,  then use the DC.Upload class (see below).

If somebody has data for you and you want to programatically download this data, use the DC.Download class (see below).

The examples below does not handle the case, where the (Cache/IRIS)Server needs an user authentication (my IRIS  System > Security Management > Web Applications is set to "Unauthenticated")

Server side (Upload)

/// Upload (i.e. provide) data to a remote party
Class DC.Upload Extends %CSP.Page
ClassMethod OnPage() As %Status
   if %request.Data("myData")]"" {
      do %request.Data("myData").OutputToDevice()
      do %request.Data("myData").%Close() }
   else {
      write "<html><head></head><body>",!
      write "Please provide a correct Password and ReportId<br>",!
      write "</body></html>",!
   quit $$$OK

ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
   if ..chkPsw(), ..chkRpt(.file) {
      set data=##class(%FileBinaryStream).%New()
      set size=##class(%File).GetFileSize(file)
      set name=##class(%File).GetFilename(file)
      do data.LinkToFile(file)
      set %response.ContentType="application/pdf"
      do %response.SetHeader("Content-Disposition","attachment;filename="_name)
      do %response.SetHeader("Content-Length",size)
      set time=$h-1
      set %response.Expires=$zd(time,11)_", "_$zd(time,2)_" 00:00:00 GMT"
      set %request.Data("myData")=data
      } else {
         set %request.Data("myData")=""
      quit $$$OK

ClassMethod chkPsw()
   set psw=$g(%request.Data("pswd",1))
   if psw]"" quit 1
   quit 0

ClassMethod chkRpt(name)
   set rpt=$g(%request.Data("rpt",1))
   if rpt]"" {
      set name="/tmp/outfiles/74LS13.pdf"
      quit 1
   quit 0


Client side (download)

/// Download (i.e. get) data from remote server
Class DC.Download Extends %RegisteredObject
ClassMethod GetFile(psw, rpt, saveTo = "/tmp/inpfiles/")
   set http=##class(%Net.HttpRequest).%New()
   set http.Server="localhost"
   set http.Port=52773
   do http.SetParam("pswd",psw)
   do http.SetParam("rpt",rpt)

   if http.Get("/csp/user/DC.Upload.cls") {
      set file=$piece($g(http.HttpResponse.Headers("CONTENT-DISPOSITION")),"=",2)
      set del=$select($zversion(1)=2:"\", 1:"/")
      set file=saveTo_$s($e(saveTo,*)=del:"",1:del)_$s(file="":"noname.dat",1:file)
      open file:"nwu":0
      if $t {
         use file
         do http.HttpResponse.Data.OutputToDevice()
         close file
         quit 1

      } else {
        quit "0,Can't open "_file

   } else {
       quit "0,"_http.HttpResponse.StatusLine

Create a temp table with all properties  you need, store it in a Cachte/IRIS-Temp unde $J of the running job (it could be, your applcation runs in several instances at the same time) an use it in your INSERT / UPDATE.

This is your Table

Class My.Table1 Extends %Persistent
Property Name As %String;
Property Age As %Numeric;

ClassMethod Test()
  d ##class(My.Temp).%DeleteId($j)
  s tmp=##class(My.Temp).%New()
  s tmp.TempID=$j, tmp.Name="Paul", tmp.Age=69
  d tmp.%Save()
  // or popolate the My.Temp via INSERT...  

  &sql(INSERT INTO My.Table1 (Name,Age)
       SELECT Name,Age FROM My.Temp WHERE TempID=$j

and this is the Temporary Table

Class My.Temp Extends %Persistent
  Parameter DEFAULTGLOBAL = "^CacheTemp.TempTable"; Property TempID As %Integer;
  Property Name As %String;
  Property Age As %Numeric;

  Index main On TempID [ IdKey ];


not a built-in, but you can easily create one

ClassMethod ParamList() [ CodeMode = objectgenerator ] As %List
set params=""
for i=1:1:%class.Parameters.Count() set params=params_$lb(%class.Parameters.GetAt(i).Name)
do %code.WriteLine($c(9)_"quit """_params_"""")

ClassMethod ParamString() As %String
quit $listtostring(..ParamList())