Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

COBOL generating XML-file with CDATA

I am trying to make a XML file in COBOL using the GENERATE statement. So far so good. But with this particular xml it needs to contain a seperate xml file within. So i want to use the CDATA tag around it. But, is there a way to do this in COBOL with the GENERATE statement?

Here an example.

   01    request.
         06    route.
         11    name                  PIC  X(030).
         11    version               PIC  9(004).
         06    question.
         11    IDENT                 PIC  9(009).
         11    xmlFileName           PIC  X(006).
         11    xmlFileInh            PIC  X(5000).

the xmlFileInh needs to be filled with another XML file. This can be only xml or a soap request.

Something like this:

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <route>
    <name>serviceRequest</name>
    <version>1</version>
  </route>
  <question>
    <IDENT>111111111</IDENT>
    <xmlFileName>FILE-1</xmlFileName>
    <xmlFileInh>
       <![CDATA[<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope.....<SOAP-ENV:Envelope]]>
    </xmlFileInh>
  </question>
</request>

I have tried to STRING the "<![CDATA[" and "]]>" around the incoming XML-file and then put it in xmlFileInh. This does something, but renders all HTML control characters into something i don't want in my xml-file. The GENERATE statement does nothing with CDATA.

< becomes   &lt;
> becomes   &gt;
" becomes   &quot;
' becomes   &apos;
& becomes   &amp;

I also tried to give xmlFileInh another picture, even type XML. That gives a lot of new sorts of tags in my XML, name-length and data-length etc. but none i want.

Does anyone have a solution?

Thanks in advance Martijn.

like image 361
Martijn Avatar asked Jul 05 '26 07:07

Martijn


2 Answers

You may not need to use CDATA at all. XML GENERATE will take the content of XMLFILEINH and escape the special characters (as you have indicated). The resultant XML when viewed with a simple text editor will show escape sequences - not what you want. However, when you use XML PARSE to process it, the escaped characters will again be replaced with their original contents. Also, most XML aware viewers (e.g. Microsoft Edge among others) will display content as you expect without the escape sequences.

Here is an example IBM Enterprise COBOL 6.2 program illustrating my point:

  IDENTIFICATION DIVISION.
  PROGRAM-ID. XML5.
  DATA DIVISION.
  WORKING-STORAGE SECTION.

  01  REQUEST.
      06 ROUTE.
        11 NAME                  PIC  X(030).
        11 VERSION               PIC  9(004).
      06 QUESTION.
        11 IDENT                 PIC  9(009).
        11 XMLFILENAME           PIC  X(006).
        11 XMLFILEINH            PIC  X(5000).


  01  XML-DOC                    PIC X(5000).
  01  XML-IDX                    PIC S9(9) BINARY.
  01  XML-CHAR-CNT               PIC S9(9) BINARY.

  PROCEDURE DIVISION.
  MAINLINE SECTION.
      MOVE 'serviceRequest' TO NAME
      MOVE 1                TO VERSION
      MOVE 111111111        TO IDENT
      MOVE 'FILE-1'         TO XMLFILENAME
      MOVE '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelop
 -         'e.....<SOAP-ENV:Envelope>'
        TO XMLFILEINH

      INITIALIZE XML-DOC
      XML GENERATE XML-DOC FROM REQUEST COUNT IN XML-CHAR-CNT
      PERFORM VARYING XML-IDX FROM 1 BY 80
                UNTIL XML-IDX > XML-CHAR-CNT
         DISPLAY XML-DOC (XML-IDX : 80)
      END-PERFORM

      XML PARSE XML-DOC PROCESSING PROCEDURE XML-HANDLER
          ON EXCEPTION
             DISPLAY 'XML Error: ' XML-CODE
             GOBACK
          NOT ON EXCEPTION
             DISPLAY 'ALL DONE.'
      END-XML
      GOBACK
      .

  XML-HANDLER.
      DISPLAY XML-EVENT (1:22) ':' XML-TEXT
      .

The output is:

<REQUEST><ROUTE><NAME>serviceRequest</NAME><VERSION>1</VERSION></ROUTE><QUESTION
><IDENT>111111111</IDENT><_XMLFILENAME>FILE-1</_XMLFILENAME><_XMLFILEINH>&lt;?xm
l version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;SOAP-ENV:Envelope..
...&lt;SOAP-ENV:Envelope&gt;</_XMLFILEINH></QUESTION></REQUEST>
START-OF-DOCUMENT     :
START-OF-ELEMENT      :REQUEST
START-OF-ELEMENT      :ROUTE
START-OF-ELEMENT      :NAME
CONTENT-CHARACTERS    :serviceRequest
END-OF-ELEMENT        :NAME
START-OF-ELEMENT      :VERSION
CONTENT-CHARACTERS    :1
END-OF-ELEMENT        :VERSION
END-OF-ELEMENT        :ROUTE
START-OF-ELEMENT      :QUESTION
START-OF-ELEMENT      :IDENT
CONTENT-CHARACTERS    :111111111
END-OF-ELEMENT        :IDENT
START-OF-ELEMENT      :_XMLFILENAME
CONTENT-CHARACTERS    :FILE-1
END-OF-ELEMENT        :_XMLFILENAME
START-OF-ELEMENT      :_XMLFILEINH
CONTENT-CHARACTERS    :<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope.....<SOAP-ENV:Envelope>
END-OF-ELEMENT        :_XMLFILEINH
END-OF-ELEMENT        :QUESTION
END-OF-ELEMENT        :REQUEST
END-OF-DOCUMENT       :
ALL DONE.

Note escaping of special characters in the "raw" dump of the generated XML, but upon completion of XML PARSE they are restored to what was given to XML GENERATE. This is normal XML processing. Character escaping such as this may protect you from code-page conversions when transmitting the generated XML. When using CDATA there is a possibility of corruption when the document has to be converted from one code page to another and there is no direct mapping for a given character (not likely but possible).

What I find interesting here, and can't explain, is why the generated XML tag names beginning with XML are prefixed with an underscore.

Final note: If the content of COBOL variable XMLFILEINH contained the sequence </_XMLFILEINH> somewhere one might think that it would cause premature ending of the <_XMLFILEINH> tag in the resulting XML. It doesn't because the opening and closing delimiters < and > are escaped on GENERATE.

like image 92
FredTheFlinstone Avatar answered Jul 09 '26 09:07

FredTheFlinstone


IBM's Enterprise COBOL does not currently have any options to deal with generating CDATA.

To solve your problem, you could leave xmlFileInh unpopulated, XML GENERATE into SOME-BUFFER then...

UNSTRING 
  SOME-BUFFER 
  DELIMITED '<xmlFileInh>' OR '</xmlFileInh>' 
  INTO 
    FIRST-PART  COUNT IN FIRST-PART-COUNT
      DELIMITER IN FIRST-DELIMITER 
    SECOND-PART
      DELIMITER IN SECOND-DELIMITER 
    THIRD-PART  COUNT IN THIRD-PART-COUNT
END-UNSTRING

...then...

STRING 
    FIRST-PART(1:FIRST-PART-COUNT)   DELIMITED SIZE
    FIRST-DELIMITER                  DELIMITED SPACE
    CDATA-CONTENT                    DELIMITED ']]>'
    ']]>'                            DELIMITED SIZE
    SECOND-DELIMITER                 DELIMITED SPACE
    THIRD-PART(1:THIRD-PART-COUNT)   DELIMITED SIZE
  INTO FINAL-DESTINATION
END-STRING

...which I've just freehanded, so no guarantees. It's also aesthetically displeasing and someone should submit an RFE to IBM to handle CDATA in XML GENERATE.

like image 32
cschneid Avatar answered Jul 09 '26 08:07

cschneid