I have a COBOL-DB2 code where it fetches the data from DB2 and moves the value to a copybook variable (XML structure). While doing XML Generate, the code fails with XML-CODE=000000417. This is because the DB2 value has a junk value. Now, I am trying to find the answers for below question. Hope someone can help
How to eliminate junk characters while doing XML Generate ? Is there any function ?
Note: Inspect/perform on the variable might be difficult before XML generate as there are multiple group variables to be XML generated. Also, for Inspect we need to know the list of Junk values.
Is there any possibility to get the list of Junk values ? Might sound silly
Any good solutions to the above issue will be very helpful. Thanks
DATA in DB2 - Ralphs Basketball Team.
You can see a junk character between h and s in Ralph_s. The Hex value of Junk is x'3F'
Code:
Fetches the data from DB2 and then,
MOVE NAME TO Name1
IN Output
MOVE ADDRESS1 TO ADDRESS
IN Output
MOVE SPACES TO WS-XML-OUTPUT
XML GENERATE WS-XML-OUTPUT FROM Output
COUNT IN WS-NUMS
SUPPRESS EVERY nonnumeric element WHEN SPACE
EVERY nonnumeric element WHEN LOW-VALUES
ON EXCEPTION
SET ERROR IN WS-ACTION
MOVE XML-CODE TO WS-XML-CODE
STRING 'XML GENERATE ERROR AT POSITION='
WS-NUMS
', XML-CODE=' WS-XML-CODE
', XML=' WS-XML-OUTPUT(1:100)
INTO WS-ERROR-TEXT
NOT ON EXCEPTION
MOVE WS-XML-OUTPUT TO WS-REC
.
.
END-XML
Note: I cannot use the below code to replace the junk with space after the DB2 fetch. This is because there are multiple group variables which needs to be XML generated and cannot use on every group variable. This might affect the performance.
Perform IX1 from 1 by 1 until IX1 > 100
IF NAME(IX1:1) < SPACE
Move space to NAME(IX1:1)
END-IF
END-PERFORM
Looking for a better solution and a generic one.
I'm going to expand a bit on the comment by @Gilbert-Le-Blanc, but please don't take this as me putting words in his mouth. There is no simple answer to your question.
You cannot do this generically. The reason you cannot do this generically is that "junk values" is context-dependent. What is "junk" in one field may not be junk in another field. What is considered to be "junk" for the purposes of your program may be required by another program processing the same column in the same DB2 table. COBOL doesn't know what you consider to be "junk values," but see below.
As an example, your program is generating XML, and the XML GENERATE has a problem with character x'3F'. Another program may be detecting the x'3F' and replacing it with x'7D' (an apostrophe).
If you can determine that all programs using a given column consider the same individual character values to be "junk values," then you could request a BEFORE INSERT OR UPDATE trigger be placed on that column, where the trigger would signal an error (or modify the data being used for INSERT or UPDATE) if the "junk values" were present, then the "junk values" would never enter the DB2 table. Note that this would probably involve processing the incoming data character-by-character. This would also involve reprocessing the existing contents of the table to ensure it conforms to the new "junk values" trigger.
Your concern about the performance of processing each field character-by-character in your program is noted, but any process by which "junk values" are replaced in your code is going to happen character-by-character whether explicitly in your code or "behind the scenes" in the code generated by the compiler or in a runtime routine.
You may be able to offset your performance concerns via multi-row fetch, which is a whole separate topic.
If your shop is not willing prevent "junk values" entering the system, then you must process each field character-by-character to replace values which offend the XML GENERATE process with values which do not. One way to do that would be...
...where you code x'40' for each "junk value" you wish replaced by a space and the same corresponding hex value for each that you do not. You must be conscious of the code page you are working with and keep in mind the code page of your DB2 table may be different from the code page of your COBOL program. Then, for each Working-Storage identifier in your program which contains character data FETCHed from your DB2 table you can code...
...and your XML GENERATE will not complain of invalid values.