Reputation: 3451
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
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
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
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
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