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 <
> becomes >
" becomes "
' becomes '
& becomes &
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.
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><?xm
l version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope..
...<SOAP-ENV:Envelope></_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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With