XML в COBOL с вложенными таблицами и различными дочерними элементами

Можно ли использовать XML GENERATE для создания XML с многоуровневыми вложенными элементами разного размера?

Например:

01  SOURCE-REC.
    05  REPEATING-PARENT OCCURS 5 TIMES.
        10  PARENT-NAME PIC X(7).
        10  CHILD-COUNT PIC 9.
        10  REPEATING-CHILD OCCURS 1 TO 5 TIMES
                DEPENDING ON CHILD-COUNT.
            15  CHILD-NAME PIC X(6).

Компиляция с использованием Enterprise Cobol v4.1 дает:

IGYGR1263-S "ПРОИСХОДИТ В ЗАВИСИМОСТИ ОТ" Объект "CHILD-COUNT" был определен как элемент таблицы. Фраза «В ЗАВИСИМОСТИ ОТ» была исключена.

IGYGR1116-S Недопустимый объект "ЗАВИСИМОСТЬ ОТ" для таблицы "ПОВТОРЯЮЩИЙСЯ-ДЕТСКИЙ". Фраза «В ЗАВИСИМОСТИ ОТ» была исключена.

Не у всех родителей будет одинаковое количество детей. Как это можно решить?

Изменить: я полагаю, что по сути это не вопрос XML. Я наткнулся на стену, просто пытаясь построить рабочее хранилище, которое я позже надеюсь передать в XML GENERATE.


person user255205    schedule 20.01.2010    source источник


Ответы (3)


Резюме первого ответа: вы не можете определить сложный ODO в COBOL, где объект ODO содержится в таблице. Следовательно, XML GENERATE не может создавать различное количество «дочерних» элементов для каждого появления «родительского». Вы должны жить с фиксированными размерами таблицы и пустыми узлами.

Раунд второй: рассматривали ли вы повторный анализ/повторное построение сгенерированной строки XML для устранения пустых узлов? Это может показаться немного странным, но это может быть не так уж и сложно. Взгляните на следующую программу и результат, который она производит...

   IDENTIFICATION DIVISION.                    
     PROGRAM-ID. EXAMPLE1.                     
   DATA DIVISION.                              
   WORKING-STORAGE SECTION.                    
   77  I                    PIC S9(4) BINARY.  
   77  XL                   PIC S9(4) BINARY.  
   77  XML-TAG              PIC X(34).         
   01  XML-DATA.                               
       05 XML-MSG-A         PIC X(8000).       
       05 XML-CHARS-A       PIC S9(4) BINARY.  
       05 XML-MSG-B         PIC X(8000).       
       05 XML-CHARS-B       PIC S9(4) BINARY.  
   01  SOURCE-REC.                             
       05  REPEATING-PARENT OCCURS 5 TIMES.    
           10  PARENT-NAME PIC X(7).           
           10  CHILD-COUNT PIC 9.              
           10  REPEATING-CHILD OCCURS 5 TIMES. 
               15  CHILD-NAME PIC X(6).        
   01  XML-STACK.                                 
       05 SP                PIC S9(4) BINARY.     
       05 STACK-REC         OCCURS 500 TIMES.     
          15 NODE-NAME      PIC X(31).            
          15 NODE-POS       PIC S9(4) BINARY.     
          15 NODE-IS-EMPTY  PIC X.                
             88 NODE-IS-EMPTY-YES VALUE 'Y'.       
             88 NODE-IS-EMPTY-NO  VALUE 'N'.       
          15 EMPTY-WHEN-IND      PIC X.                
             88 EMPTY-ZERO-OR-SPACE  VALUE 'Z'.   
             88 EMPTY-NEVER          VALUE 'N'.   
   PROCEDURE DIVISION.                            
       INITIALIZE SOURCE-REC.                     
       MOVE 'p-1'       TO PARENT-NAME (1)        
       MOVE 2           TO CHILD-COUNT (1)        
       MOVE 'c-1-1'     TO CHILD-NAME  (1 1)      
       MOVE 'c-1-2'     TO CHILD-NAME  (1 2)      
       MOVE 'p-2'       TO PARENT-NAME (2)        
       MOVE 0           TO CHILD-COUNT (2)        
       MOVE 'p-3'       TO PARENT-NAME (3)                        
       MOVE 1           TO CHILD-COUNT (3)                        
       MOVE 'c-3-1' TO CHILD-NAME  (3 1)                          

       XML GENERATE XML-MSG-A FROM SOURCE-REC COUNT IN XML-CHARS-A
       MOVE ZERO TO XML-CHARS-B                                   
       MOVE SPACES TO XML-MSG-B                                   
       XML PARSE XML-MSG-A(1:XML-CHARS-A)                         
           PROCESSING PROCEDURE CLEAN-UP                          
       PERFORM VARYING I FROM 1 BY 80 UNTIL I > XML-CHARS-B       
         DISPLAY XML-MSG-B (I:80)                                 
       END-PERFORM                                                
       GOBACK                                                     
       .                                                          
   CLEAN-UP SECTION.                                              
       COMPUTE XL = FUNCTION LENGTH (XML-TEXT)                    
       EVALUATE XML-EVENT                                         
       WHEN 'START-OF-ELEMENT'                                    
          ADD 1 TO SP                                             
          MOVE XML-TEXT(1:XL) TO NODE-NAME (SP)                      
          COMPUTE NODE-POS (SP) = XML-CHARS-B + 1              
          STRING '<' XML-TEXT(1:XL) '>' DELIMITED BY SIZE           
            INTO XML-TAG                                      
          MOVE XML-TAG TO XML-MSG-B (XML-CHARS-B + 1:XL + 2)  
          COMPUTE XML-CHARS-B = XML-CHARS-B + XL + 2          
          SET NODE-IS-EMPTY-YES (SP) TO TRUE                   
 *****    EVALUATE XML-TEXT(1:XL)                                   
 *****    WHEN 'CHILD-COUNT'                                  
 *****       SET EMPTY-NEVER (SP) TO TRUE                     
 *****    WHEN OTHER                                          
             SET EMPTY-ZERO-OR-SPACE (SP) TO TRUE             
 *****    END-EVALUATE                                        
       WHEN 'CONTENT-CHARACTERS'                              
          IF EMPTY-ZERO-OR-SPACE (SP) AND                     
             (XML-TEXT(1:XL) = ZERO OR XML-TEXT(1:XL) = SPACE)            
             CONTINUE                                         
          ELSE                                                
             SET NODE-IS-EMPTY-NO (SP) TO TRUE                 
             MOVE XML-TEXT(1:XL) TO XML-MSG-B (XML-CHARS-B + 1:XL)     
             COMPUTE XML-CHARS-B = XML-CHARS-B + XL              
          END-IF                                                 
       WHEN 'END-OF-ELEMENT'                                     
          IF NODE-IS-EMPTY-YES (SP)                               
             COMPUTE XML-CHARS-B = NODE-POS (SP) - 1              
             SUBTRACT 1 FROM SP                                  
          ELSE                                                   
             STRING '</' XML-TEXT(1:XL) '>' DELIMITED BY SIZE          
               INTO XML-TAG                                      
             MOVE XML-TAG TO XML-MSG-B (XML-CHARS-B + 1:XL + 3)  
             COMPUTE XML-CHARS-B = XML-CHARS-B + XL + 3          
             SUBTRACT 1 FROM SP                                  
             IF SP > ZERO                                        
               SET NODE-IS-EMPTY-NO (SP) TO TRUE                  
             ELSE                                                
               MOVE SPACES TO XML-MSG-B (XML-CHARS-B + 1:)       
             END-IF                                              
          END-IF                                                 
       END-EVALUATE         
       .                    

Дает вам следующую строку XML (разрезанную на фрагменты по 80 символов)

<SOURCE-REC><REPEATING-PARENT><PARENT-NAME>p-1</PARENT-NAME><CHILD-COUNT>2</CHIL
D-COUNT><REPEATING-CHILD><CHILD-NAME>c-1-1</CHILD-NAME></REPEATING-CHILD><REPEAT
ING-CHILD><CHILD-NAME>c-1-2</CHILD-NAME></REPEATING-CHILD></REPEATING-PARENT><RE
PEATING-PARENT><PARENT-NAME>p-2</PARENT-NAME></REPEATING-PARENT><REPEATING-PAREN
T><PARENT-NAME>p-3</PARENT-NAME><CHILD-COUNT>1</CHILD-COUNT><REPEATING-CHILD><CH
ILD-NAME>c-3-1</CHILD-NAME></REPEATING-CHILD></REPEATING-PARENT></SOURCE-REC>   

Все пустые узлы были удалены.

Обратите внимание на закомментированные строки кода в приведенной выше программе. Повторно активировав их, вы можете сохранить пустые узлы REPEATING-PARENT. В зависимости от ваших потребностей определение того, что представляет собой пустой узел, может быть несколько более сложным.

Во всяком случае, это может немного приблизить вас к тому, чего вы хотите.

Ваше здоровье...

person NealB    schedule 22.01.2010
comment
Нил, ты гений. Это действительно спасло меня от неприятного проекта, над которым я работал. Пара предложений: я думаю, что SET EMPTY-ZERO-OR-SPACE (SP) TO TRUE также следует закомментировать в закомментированном разделе. Кроме того, мне пришлось разграничивать мой XML-ТЕКСТ пробелом, а не делать все это по размеру во время строки, чтобы не допустить появления отсутствующего символа. - person Marcus_33; 21.12.2011

Я думаю, проблема в том, что CHILD-COUNT должен быть определен вне структуры записи, переданной в XML GENERATE. Что-то типа:


01  CHILD-COUNT PIC 9.
01  SOURCE-REC. 
    05  REPEATING-PARENT OCCURS 5 TIMES. 
        10  PARENT-NAME PIC X(7). 
        10  CHILD-COUNTER PIC 9. 
        10  REPEATING-CHILD OCCURS 1 TO 5 TIMES 
                DEPENDING ON CHILD-COUNT. 
            15  CHILD-NAME PIC X(6).

Затем непосредственно перед XML GENERATE вам нужно будет сделать что-то вроде:


MOVE CHILD-COUNT TO CHILD-COUNTER (PARENT-COUNT)

если вы хотите сохранить количество вхождений для REPEATING-CHILD

Вероятно, это не то, что вы хотели увидеть, потому что в значительной степени это означает, что вы должны иметь одинаковое количество зависимых дочерних элементов для каждого вхождения REPEATING-PARENT.

person NealB    schedule 20.01.2010
comment
Это суть проблемы, которую я пытаюсь решить. Количество детей у каждого родителя разное. Родитель 1 может иметь 3 детей. Родитель 2 может иметь 1 ребенка. Извините, если это было непонятно. - person user255205; 21.01.2010
comment
По сути, вы не можете этого сделать, потому что исходное определение записи не является допустимой сложной структурой записи ODO, см.: publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/IGY3PG31/ - person NealB; 21.01.2010

Я думаю, что вы должны полностью отказаться от ЗАВИСИМОСТИ ОТ. Это не экономит память, и вы можете так же легко обращаться к действительным элементам REPEATING-CHILD, убедившись, что их индексы находятся в диапазоне от 1 до соответствующего CHILD-COUNTER.

person Albert Visser    schedule 20.01.2010
comment
Проблема с этим решением заключается в том, что XML GENERATE по-прежнему будет создавать узлы в XML для незаполненных дочерних элементов. Этот пример родитель/потомок очень прост, всего два уровня и пара элементов. Данные, с которыми я фактически работаю, намного больше, и влияние вывода пустых элементов огромно. - person user255205; 21.01.2010
comment
да я боялась этого. Я не очень хорошо знаком с опцией создания XML, в основном знаю ее о — в моей компании мы должны позволить брокеру веб-сообщений преобразовывать фиксированные записи в XML — но это имеет смысл для автоматизированного решения - person Albert Visser; 22.01.2010