Hi,
I don't have a lot of time to spend on this today, but I will offer a few quick tips:
1) You can have multiple set statements in the same data step.
2) You can use the NOBS= set statement option to get the number of observations in the input data set AT COMPILE TIME. IOW, you can reference the nobs variable "before" you define it in your set statement. I say "before" because it's not before; it's actually defined during the data step compilation.
3) You can use the POINT= set statement option to specify the particular observation (row) you want to read from the input data set.
4) The data step ends when any of the set statements tries to read past the end of its input data set. The POINT= option prevents that. (It also means you can code an infinite loop with the POINT= option if you're not careful). The POINT= option allows you to "rewind" the data set based on the POINT= value at run time.
5) Each time the set statement executes, it reads a row from the input data set and populates the Program Data Vector (PDV).
6) A data set variable (as opposed to a data *step* variable) has an implied retain. This means you can use a conditional set statement, and the data set variable is carried forward from the last time the set statement executed (due to the implied retain). (This may or may not be relevant to your problem statement).
Putting this all together:
data x (keep=x)
y (keep=y)
z (keep=z)
;
do x=1 to 10;
y=x*2;
z=x*3;
output x;
if x <= 5 then output y;
if x > 5 then output z;
end;
run;
data test;
set x;
do i=1 to nobs_y;
set y nobs=nobs_y point=i;
do j=1 to nobs_z;
if mod(j,2)=1 then set z nobs=nobs_z point=j;
output;
end;
end;
* don't need to drop i and j because they are used with point= ;
run;
* dynamic processing ;
* you can't use a where clause but you can use an if statement ;
data test2;
set x; /* 1 to 10 */
_y=x*3; /* 3,6,9, etc */
_z=x*4; /* 4,8,16, etc */
* still need point= to prevent reading past end of file ;
* it allows "rewinding" the dataset each time ;
do i=1 to nobs_y;
set y nobs=nobs_y point=i;
if y < _y;
do j=1 to nobs_z;
set z nobs=nobs_z point=j;
if z < _z;
output;
end;
end;
* drop _:;
run;
Hopefully you can wrap your head around this.
This means you may be able to drop much of your macro processing where you were running a secondary data step, specifying if _n_=<some number>, then creating macro variables to use in downstream processing.
Lastly, do you have, and have you ever used, the XMLMAPPER application? It is a Java program supplied by SAS that creates a UI, where you can create an XML map. Usually this is a map of an input XML file, flattening that file into a tabular format that is then used to read the data into SAS. Check Start -> Programs -> SAS. You'll either see XMLMAPPER or you won't. If not, check with your SAS administrator. AFAIK, there are no licensing issues - XMLMAPPER is a free utility provided by SAS.
An XML map can also be used to specify an output XML file format. It's been a while since I've used it, but you may be able to create an XML map that will create the output format you want. If so, the process would be to flatten (merge, join, etc) your data so that your combined SAS dataset is how you want to represent your data. You would then use a data step, PROC PRINT, PROC REPORT, etc. to "print" your SAS dataset to your output XML fileref, supplying the XML map as a parameter to your filename statement.
Otherwise, as Tom said, you could just hand generate your XML tags.
HTH...
Edit: If you have installation rights on your machine (and perhaps even if you don't - you don't HAVE to install to C:\Program Files), then it looks like XML mapper is a free download:
https://support.sas.com/downloads/package.htm?pid=713
... View more