Help using Base SAS procedures

How to fetch specific tags in XML files and put those lines into another one

Accepted Solution Solved
Reply
SAS Employee
Posts: 7
Accepted Solution

How to fetch specific tags in XML files and put those lines into another one

Hi,

I am trying to fetch FlowDefinition tag in a file having such a structure summarized below.

__________________________


<GetFlowResponse xmlns="?"><FlowDefinition eventName="KKB_Bireysel_Master" lastModifiedBy="sasdemo" modified="2015-04-21T15:27:05.840Z" created="2015-04-21T15:27:05.840Z" displayName="Campaign279Smiley Frustratedhared Data\Decision Tree:KKB Business Context" name="Campaign279_1_DFDFEPEM5ZGTUVVA">

                        <Description>Campaign279Smiley Frustratedhared Data\Decision Tree:KKB Business Context

</Description>

…………….

…………

</FlowDefinition></GetFlowResponse>

__________________________


After having all lines between "<FlowDefinition" and "</FlowDefinition>", using these lines I want to replace another xml file(as below) which also includes FlowDefinition tag with my new FlowDefinition tag. And finally, I want to add "ns2:" prefix to each tag.

__________________________


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtd="?">

   <soapenv:Header/>

   <soapenv:Body>

      <rtdSmiley FrustratedubmitSimulation>

         <rtdSmiley FrustratedessionContextId>?</rtdSmiley FrustratedessionContextId>

         <rtd:RepositoryName>?</rtd:RepositoryName>

         <!--Zero or more repetitions:-->

         <rtd:FlowDefinition name="?" displayName="" created="?" modified="?" lastModifiedBy="?" activated="?" eventName="?" timeout="0" timeoutEnabled="false">

…………….

…………

</rtd:FlowDefinition>

         <!--Zero or more repetitions:-->

         <rtd:GlobalValue name="?">

            <!--Zero or more repetitions:-->

            <rtd:Value>?</rtd:Value>

         </rtd:GlobalValue>

         <rtdSmiley FrustratedimulationDescription eventName="?" inLibraryName="?" inTableName="?" outLibraryName="?" outTableName="?" statsLibraryName="?" statsTableName="?" overwriteOutputTable="?" multiThreaded="?" timeZoneOptions="?" timeZoneColumnOrId="?"/>

      </rtdSmiley FrustratedubmitSimulation>

   </soapenv:Body>

</soapenv:Envelope>

__________________________

So 3 things to code:

1. Fetch FlowDefinition tag from one xml files.

2. Replace an old FlowDefinition tag in another xml file with the new FlowDefinition tag.

3. Add prefix(ns2Smiley Happy to each tag.

What is the best way to code those? Any comment will be appreciated. Thanks a lot!

Regards,

Ozge


Accepted Solutions
Solution
‎12-11-2015 08:54 AM
Grand Advisor
Posts: 9,444

Re: How to fetch specific tags in XML files and put those lines into another one

Code: Program4.sas

data have;
infile cards length=len ;
input x $varying2000. len;
cards;
<GetFlowResponse xmlns="?"><FlowDefinition eventName="KKB_Bireysel_Master" lastModifiedBy="sasdemo" modified="2015-04-21T15:27:05.840Z" created="2015-04-21T15:27:05.840Z" displayName="Campaign279:Shared Data\Decision Tree:KKB Business Context" name="Campaign279_1_DFDFEPEM5ZGTUVVA">
  <Description>Campaign279:Shared Data\Decision Tree:KKB Business Context
</Description>
…………….
…………
</FlowDefinition></GetFlowResponse>
;
run;

data x;
infile cards length=len ;
input x $varying2000. len;
cards;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtd="?">
  <soapenv:Header/>
  <soapenv:Body>
  <rtd:SubmitSimulation>
  <rtd:SessionContextId>?</rtd:SessionContextId>
  <rtd:RepositoryName>?</rtd:RepositoryName>
  <!--Zero or more repetitions:-->
  <rtd:FlowDefinition name="?" displayName="" created="?" modified="?" lastModifiedBy="?" activated="?" eventName="?" timeout="0" timeoutEnabled="false">
…………….
…………
</rtd:FlowDefinition>
  <!--Zero or more repetitions:-->
  <rtd:GlobalValue name="?">
  <!--Zero or more repetitions:-->
  <rtd:Value>?</rtd:Value>
  </rtd:GlobalValue>
  <rtd:SimulationDescription eventName="?" inLibraryName="?" inTableName="?" outLibraryName="?" outTableName="?" statsLibraryName="?" statsTableName="?" overwriteOutputTable="?" multiThreaded="?" timeZoneOptions="?" timeZoneColumnOrId="?"/>
  </rtd:SubmitSimulation>
  </soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtd="?">
  <soapenv:Header/>
  <soapenv:Body>
  <rtd:SubmitSimulation>
  <rtd:SessionContextId>?</rtd:SessionContextId>
  <rtd:RepositoryName>?</rtd:RepositoryName>
  <!--Zero or more repetitions:-->
  <rtd:FlowDefinition name="?" displayName="" created="?" modified="?" lastModifiedBy="?" activated="?" eventName="?" timeout="0" timeoutEnabled="false">
…………….
…………
</rtd:FlowDefinition>
  <!--Zero or more repetitions:-->
  <rtd:GlobalValue name="?">
  <!--Zero or more repetitions:-->
  <rtd:Value>?</rtd:Value>
  </rtd:GlobalValue>
  <rtd:SimulationDescription eventName="?" inLibraryName="?" inTableName="?" outLibraryName="?" outTableName="?" statsLibraryName="?" statsTableName="?" overwriteOutputTable="?" multiThreaded="?" timeZoneOptions="?" timeZoneColumnOrId="?"/>
  </rtd:SubmitSimulation>
  </soapenv:Body>
</soapenv:Envelope>
;
run;



data tag;
set have;
retain found;
p=find(x,'<FlowDefinition');
if p then do;
  found=1;
  x=cats('<ns2:',substr(x,p+1));
end;
p=find(x,'</FlowDefinition>');
if p then do;
  x=cats('</ns2:',substr(x,p+2,15));
end;
if find(lag(x),'</FlowDefinition>') then found=0;
if found;
keep x;
run;

data temp;
set x;
retain found;
if find(x,'<rtd:FlowDefinition') then found=1;
if find(lag(x),'</rtd:FlowDefinition>') then found=0;
if not found or (not lag(found) and found);
run;
data want;
set temp;
if not found then output;
   else do;
   do i=1 to nobs;
   set tag point=i nobs=nobs;
   output;
   end;
   end;
run;

View solution in original post


All Replies
Esteemed Advisor
Esteemed Advisor
Posts: 6,971

Re: How to fetch specific tags in XML files and put those lines into another one

Well, my honest opinion?  I would suggest you either use a proper XML tool - Oxyen/XML Spy (which is free), or maybe if you need to code it, then .net and XPath.  You can then operate on nodes very simply:

- set document a, set document b

- parse document a, set document b

- set node<xyz> from file b to node<xyz> from file a

- write out document b

Now you could do this in SAS, i.e. create a map file, import both data, process that data, then output the files.  Personally I find SAS interaction with XML is not very good, mainly as it is a different technology, so best to use the tools built to deal with that technology.

You could, if textually speaking, find that string, i.e. if line read in ="<Flowdefinition>...", then you could just do a:

data _null_;

     infile "xyz.xml";

     file "xyz2.xml";

     input buffer $2000.;

     if index(buffer)="<FlowDefinition" then do;

          write out your extra bits here...

     end;

     else put buffer;

run;

However you have to be sure you know whats coming in and what your changing as its just plain text, you can't access "nodes".

SAS Employee
Posts: 7

Re: How to fetch specific tags in XML files and put those lines into another one

Hi RW9,

Thanks for your quick response. Unfortunately I am supposed to maintain it with SAS coding. So, I have to assume it as a text file. I have tried your code sample as below. However, the result is not as expected. I want to get the all lines between FlowDefinition but can get the following results. Do you have any comments?

___________________

FILENAME response '/sas/MPayment_Project/XML_Files/getFlow_resp.xml';

FILENAME flowdef2 '/sas/MPayment_Project/XML_Files/flowdef2.xml';

data _null_;

     infile response;

     file flowdef2;

     input buffer $20000.;

     if (index(buffer,"<FlowDefinition")>0) then do;

    

     end;

  else; put buffer;

run;

_____________________

RESULT:

TableColumnsAdd(_G_IO_READ_COLUMNS_TO_READ, { { 'TID', 'STRING' }, { 'TCKN_VKN', 'STRING' }, { 'RESULT', 'STRING' }, { 'RESULT_TYPE', 'STRING' }, { 'RESULT_CODE', 'STRING' }, { 'RESULT_DATETIME', 'DATETIME' } });</Expression></CodeNode><CodeNode displayNam

TableRowsAdd(_G_IO_INSERT_TABLE_VALUES, { { _RQST_TCKN_1J2FM_C, _TODAYS_DATETIME } });</Expression></CodeNode><CodeNode displayName="Cell" name="DGEHRLGYPJCAU3HN"><Transition name="ToReply"><Rule>true</Rule><DestinationNodeName>BEFCQDTZUJGITU1X</Destinatio

_CELL_DESC=.;

_RESPONSE_TRACKING_CODE="10380201";

_TOTAL_TREATMENTS = 0;

</Expression></CodeNode><CodeNode displayName="" name="standardReplyContext"><Description/><Transition name="TostandardReplyContext_3"><Rule>true</Rule><DestinationNodeName>standardReplyContext_3</DestinationNodeName></Transition><Expression>_CELL_NAME="";

_CELL_DESC="";

_REPLY_PACK_CODE="1039";

</Expression></CodeNode></FlowDefinition></GetFlowResponse>

Esteemed Advisor
Esteemed Advisor
Posts: 6,971

Re: How to fetch specific tags in XML files and put those lines into another one

The first way I thought about was to have a trigger on/off e.g.:

...

     retain flag;

     if _n_=1 then flag=0;

     if index(buffer,"<FlowDefinition")>0 then flag=1;

     if flag=1 then do;

          do you processing here

     end;

     if index(buffer,"/FlowDefinition>")>0 then flag=0;

...

Solution
‎12-11-2015 08:54 AM
Grand Advisor
Posts: 9,444

Re: How to fetch specific tags in XML files and put those lines into another one

Code: Program4.sas

data have;
infile cards length=len ;
input x $varying2000. len;
cards;
<GetFlowResponse xmlns="?"><FlowDefinition eventName="KKB_Bireysel_Master" lastModifiedBy="sasdemo" modified="2015-04-21T15:27:05.840Z" created="2015-04-21T15:27:05.840Z" displayName="Campaign279:Shared Data\Decision Tree:KKB Business Context" name="Campaign279_1_DFDFEPEM5ZGTUVVA">
  <Description>Campaign279:Shared Data\Decision Tree:KKB Business Context
</Description>
…………….
…………
</FlowDefinition></GetFlowResponse>
;
run;

data x;
infile cards length=len ;
input x $varying2000. len;
cards;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtd="?">
  <soapenv:Header/>
  <soapenv:Body>
  <rtd:SubmitSimulation>
  <rtd:SessionContextId>?</rtd:SessionContextId>
  <rtd:RepositoryName>?</rtd:RepositoryName>
  <!--Zero or more repetitions:-->
  <rtd:FlowDefinition name="?" displayName="" created="?" modified="?" lastModifiedBy="?" activated="?" eventName="?" timeout="0" timeoutEnabled="false">
…………….
…………
</rtd:FlowDefinition>
  <!--Zero or more repetitions:-->
  <rtd:GlobalValue name="?">
  <!--Zero or more repetitions:-->
  <rtd:Value>?</rtd:Value>
  </rtd:GlobalValue>
  <rtd:SimulationDescription eventName="?" inLibraryName="?" inTableName="?" outLibraryName="?" outTableName="?" statsLibraryName="?" statsTableName="?" overwriteOutputTable="?" multiThreaded="?" timeZoneOptions="?" timeZoneColumnOrId="?"/>
  </rtd:SubmitSimulation>
  </soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtd="?">
  <soapenv:Header/>
  <soapenv:Body>
  <rtd:SubmitSimulation>
  <rtd:SessionContextId>?</rtd:SessionContextId>
  <rtd:RepositoryName>?</rtd:RepositoryName>
  <!--Zero or more repetitions:-->
  <rtd:FlowDefinition name="?" displayName="" created="?" modified="?" lastModifiedBy="?" activated="?" eventName="?" timeout="0" timeoutEnabled="false">
…………….
…………
</rtd:FlowDefinition>
  <!--Zero or more repetitions:-->
  <rtd:GlobalValue name="?">
  <!--Zero or more repetitions:-->
  <rtd:Value>?</rtd:Value>
  </rtd:GlobalValue>
  <rtd:SimulationDescription eventName="?" inLibraryName="?" inTableName="?" outLibraryName="?" outTableName="?" statsLibraryName="?" statsTableName="?" overwriteOutputTable="?" multiThreaded="?" timeZoneOptions="?" timeZoneColumnOrId="?"/>
  </rtd:SubmitSimulation>
  </soapenv:Body>
</soapenv:Envelope>
;
run;



data tag;
set have;
retain found;
p=find(x,'<FlowDefinition');
if p then do;
  found=1;
  x=cats('<ns2:',substr(x,p+1));
end;
p=find(x,'</FlowDefinition>');
if p then do;
  x=cats('</ns2:',substr(x,p+2,15));
end;
if find(lag(x),'</FlowDefinition>') then found=0;
if found;
keep x;
run;

data temp;
set x;
retain found;
if find(x,'<rtd:FlowDefinition') then found=1;
if find(lag(x),'</rtd:FlowDefinition>') then found=0;
if not found or (not lag(found) and found);
run;
data want;
set temp;
if not found then output;
   else do;
   do i=1 to nobs;
   set tag point=i nobs=nobs;
   output;
   end;
   end;
run;

SAS Employee
Posts: 7

Re: How to fetch specific tags in XML files and put those lines into another one

Perfect solution, thx a lot!
☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 5 replies
  • 374 views
  • 1 like
  • 3 in conversation