COBOL генерирует XML-файл с CDATA

Я пытаюсь создать XML-файл на COBOL с помощью оператора GENERATE. Все идет нормально. Но с этим конкретным xml он должен содержать отдельный XML-файл внутри. Поэтому я хочу использовать вокруг него тег CDATA. Но есть ли способ сделать это в COBOL с помощью оператора GENERATE?

Вот пример.

   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).

xmlFileInh необходимо заполнить другим файлом XML. Это может быть только xml или запрос на мыло.

Что-то вроде этого:

<?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>

Я попытался нанести СТРОКУ "<![CDATA[" and "]]>" вокруг входящего XML-файла, а затем поместить его в xmlFileInh. Это что-то делает, но преобразует все управляющие символы HTML в то, что мне не нужно в моем xml-файле. Оператор GENERATE ничего не делает с CDATA.

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

Я также пытался передать xmlFileInh другую картинку, даже типа XML. Это дает много новых типов тегов в моем XML, длину имени, длину данных и т. Д., Но я не хочу ни одного.

у кого-нибудь есть решение?

Заранее спасибо Martijn.


person Martijn    schedule 26.02.2020    source источник


Ответы (3)


Возможно, вам вообще не нужно использовать CDATA. XML GENERATE берет содержимое XMLFILEINH и экранирует специальные символы (как вы указали). Результирующий XML при просмотре с помощью простого текстового редактора покажет escape-последовательности, а не то, что вы хотите. Однако, когда вы используете XML PARSE для его обработки, экранированные символы снова будут заменены их исходным содержимым. Кроме того, большинство средств просмотра, поддерживающих XML (например, Microsoft Edge), будут отображать контент так, как вы ожидаете, без escape-последовательностей.

Вот пример программы IBM Enterprise COBOL 6.2, иллюстрирующий мою точку зрения:

  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
      .

Результат:

<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.

Обратите внимание на экранирование специальных символов в «необработанном» дампе сгенерированного XML, но после завершения XML PARSE они восстанавливаются до того, что было передано в XML GENERATE. Это нормальная обработка XML. Подобное экранирование символов может защитить вас от преобразования кодовой страницы при передаче сгенерированного XML. При использовании CDATA существует вероятность повреждения, когда документ необходимо преобразовать из одной кодовой страницы в другую и нет прямого сопоставления для данного символа (маловероятно, но возможно).

Что мне здесь интересно и что я не могу объяснить, так это то, почему сгенерированные имена тегов XML, начинающиеся с XML, имеют префикс с подчеркиванием.

Заключительное примечание: если содержимое переменной COBOL XMLFILEINH содержит последовательность </_XMLFILEINH> где-то, можно подумать, что это вызовет преждевременное завершение тега <_XMLFILEINH> в результирующем XML. Это не так, потому что открывающие и закрывающие ограничители < и > экранируются при GENERATE.

person FredTheFlinstone    schedule 26.02.2020

IBM Enterprise COBOL в настоящее время не имеет никаких вариантов для создания CDATA.

Чтобы решить вашу проблему, вы можете оставить xmlFileInh незаполненным, затем XML GENERATE в SOME-BUFFER ...

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

...тогда...

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

... которую я только что отдал на произвол судьбы, так что никаких гарантий. Это также неприятно с эстетической точки зрения, и кто-то должен отправить в IBM RFE для обработки CDATA в XML GENERATE.

person cschneid    schedule 26.02.2020

Прочитав ответ @FredTheFlinstone, я понял, что это именно то, что нужно моей ситуации. XML, сгенерированный со встроенным xml внутри, обрабатывается другой программой COBOL. Поэтому я использовал решение без добавления CDATA перед концом в конце встроенного XML.

Здесь есть несколько дополнительных моментов (в моем случае):

XML, который должен быть помещен в XMLFILEINH, поступает из MQ в UTF-8. Переменные в REQUEST находятся в рабочем хранилище, поэтому EBCDIC. GENERATE должен создать REQUEST-xml в UTF-8, поэтому я добавил ENCODING 1208. GENERATE нужны все поля в EBCDIC, поэтому мне сначала нужно преобразовать ввод с помощью функций DISPLAY-OF и NATIONAL-OF.

Также не забудьте инициализировать завершающие символы в XMLFILEINH. Оператором GENERATE удаляются только пробелы. Очевидно, но полезно знать.

Наконец, о подчеркивании в тэгах, начинающихся с XML. Понятия не имею. Я думаю, это из-за имени в нем «XML»? Это был всего лишь пробный запрос, чтобы уточнить мой вопрос. Для создания ЗАПРОСА я использую другие слова, а не XML. Нет подчеркиваний.

Если бы мой запрос должен был выйти за пределы среды COBOL мэйнфрейма, мне, возможно, пришлось бы использовать другой вариант, указанный здесь @cschneid. Я также передам сообщение нашим техническим специалистам, которые работают с IBM.

Хотя, возможно, из-за того, что символы excape кажутся стандартным использованием xml, другие парсеры на других платформах справляются с этим так же. Но остается вопрос, зачем вообще использовать CDATA ... Он должен быть для чего-то полезен.

В любом случае спасибо за ответы! Это решило мою проблему.

person Martijn    schedule 28.02.2020