Thalecress
Thalecress

Reputation: 3451

COBOL XML PARSE equivalent of innerXML?

I'm trying to access the entire "< mynode >" node in the sample XML below, including start and end tags. I need to store that snippet of XML as XML in a database.

<a>
  <mynode >
   <c>Content</c>
   <c>More content</c>
  </mynode >
</a>

I have access to the XML PARSE function, and that's how I've been accessing node values, but I'm not sure how to use it to access an entire node.

One option that came to mind was recording document locations where start-of-element and end-of-element XML-TEXT = 'b', and then taking that portion of the document, but that seems inelegant. Is there a better way?

Edit: I count how many characters I've read into the document, and store that value when I reach the start and end of the "< mynode >" node.

Then I can access the document with

STRING MY-DOCUMENT(MYNODE-START-POSE, (MYNODE-NODE-FINISH - MYNODE-NODE-START)) 
     DELIMITED BY SIZE
     INTO MY-AREA

Upvotes: 1

Views: 2819

Answers (4)

Shady Dave
Shady Dave

Reputation: 1

I may be a little late with this reply now but we use the Redvers COBOL XML Interface parser which has an "ASIS" feature that reads the entire content of a node/parent element into a single COBOL copybook field - complete with any XML mark-up and subordinate elements. It's a DOM style parser. The generator module can do the opposite, giving you the ability to load pre-prepared XML to an instance document.

Upvotes: 0

NealB
NealB

Reputation: 16928

COBOL XML PARSE does not provide positional information (AFAIK). Determining the offset position where a given event occurs is not possible. A text seach for the tag of interest is bound to lead to heaps of problems - don`t even think of going there...

The next possibility I can think of is to construct XML fragment document of interest during a parse of the original document. When the fragment is complete, write it to your XML database.

The example program below illustrates how you might go about doing that. This program takes an XML-SOURCE document and parses it looking for events of interst (eg. 'b' tags). When such a tag is found it begins constructing a fragment document (XML-FRAGMENT) until the closing tag is found. At this point the fragment is output and the search for the next fragment begins.

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

   77  XL                   PIC S9(4) BINARY. 

   01.                      PIC X.            
       88 XML-EXTRACT-NO    VALUE 'N'.        
       88 XML-EXTRACT-YES   VALUE 'Y'.        

   01.                                        
       05 XML-FRAGMENT      PIC X(8000).      
       05 XML-CHARS         PIC S9(4) BINARY. 

   01  XML-SOURCE           PIC X(8000). 

   PROCEDURE DIVISION.                                         
   MAINLINE SECTION.   

       MOVE '<a><b><c>Content</c><c>More content</c></b></a>'
         TO XML-SOURCE                                         

       SET XML-EXTRACT-NO TO TRUE                              
       XML PARSE XML-SOURCE                                    
           PROCESSING PROCEDURE XTRACT                         
       GOBACK                                                  
       .                                                       
   XTRACT SECTION.                                             
       COMPUTE XL = FUNCTION LENGTH (XML-TEXT)                 
       EVALUATE XML-EVENT                                      
       WHEN 'START-OF-ELEMENT'
  *
  *       New XML element: Ignore it, add to existing fragment
  *       or start a new fragment...
  *                                                                 
          IF XML-TEXT(1:XL) = 'b' OR XML-EXTRACT-YES           
             IF XML-EXTRACT-NO                                 
                MOVE ZERO TO XML-CHARS                         
                SET XML-EXTRACT-YES TO TRUE                    
             END-IF                                            
             STRING '<' XML-TEXT(1:XL) '>' DELIMITED BY SIZE        
               INTO XML-FRAGMENT(XML-CHARS + 1 : XL + 2)            
             COMPUTE XML-CHARS = XML-CHARS + XL + 2                 
          END-IF                                                    
       WHEN 'END-OF-ELEMENT'
  *
  *       End of event: Add to XML fragment, ignore fragment or
  *                     output complete fragment and start search
  *                     for a new one...
  *                                        
          IF XML-EXTRACT-YES                                        
             STRING '</' XML-TEXT(1:XL) '>' DELIMITED BY SIZE       
               INTO XML-FRAGMENT(XML-CHARS + 1 : XL + 3)            
             COMPUTE XML-CHARS = XML-CHARS + XL + 3                 
          END-IF

          IF XML-TEXT(1:XL) = 'b'                                   
  *                                                                 
  *          End of fragment write to database (or whatever)               
  *                                                                 
             DISPLAY XML-FRAGMENT(1:XML-CHARS) 
             SET XML-EXTRACT-NO TO TRUE        
          END-IF
       WHEN 'CONTENT-CHARACTERS'
  *
  *       Add event data to fragment or just ignore it...
  *
  *       Depening on the structure of your XML docuemnt you may
  *       need to react to addtional EVENTS such as CDATA to ensure
  *       proper tag construction.
  *
          IF XML-EXTRACT-YES                                        
             MOVE XML-TEXT(1:XL) TO XML-FRAGMENT(XML-CHARS + 1 : XL)
             COMPUTE XML-CHARS = XML-CHARS + XL                     
          END-IF                                                    

       END-EVALUATE                            
       .                                       

The ouput from this program example is:

 <b><c>Content</c><c>More content</c></b>

This isn't the one-line solution you might have been looking for, but you have to remember this is COBOL!

Upvotes: 2

David Gorsline
David Gorsline

Reputation: 5018

XML parsing is a little tricky, in any language. I would recommend finding a parser library for your specific COBOL environment. This article gives a brief overview of the XML parsing landscape. Think about whether you need to pass the XML file once, extracting your desired information as you go (a SAX approach will work for you) or whether you want to load the XML into memory and traverse its structure (you want access to the DOM [Document Object Model]).

In fact, your COBOL dialect may have XML support built in (something my old COBOL 85 compiler didn't have), with the XML PARSE statement.

And here's a little information from the Micro Focus world.

Upvotes: 1

cschneid
cschneid

Reputation: 10775

If you are using IBM's Enterprise COBOL then you have an XML PARSE statement available. The parser generates events and populates special registers which are available to you to govern execution of your code. (for some reason that last link doesn't work properly, it's supposed to take you to the "Control flow" tag on that page)

If you need to "prune" parts of the tree structure, including tags and data, then you might want to parse the original, populate a structure, and use XML GENERATE to get the XML datastream you want. It doesn't look like the parser is going to tell you the location in the original XML datastream where each event takes place, at least there doesn't seem to be a special register that gets populated with that value.

Upvotes: 3

Related Questions