1

我正在尝试访问下面示例 XML 中的整个“< mynode >”节点,包括开始和结束标记。我需要将该 XML 片段作为 XML 存储在数据库中。

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

我可以访问 XML PARSE 函数,这就是我访问节点值的方式,但我不确定如何使用它来访问整个节点。

想到的一个选项是记录元素开始和元素结束 XML-TEXT = 'b' 的文档位置,然后获取文档的该部分,但这似乎不优雅。有没有更好的办法?

编辑:我计算我读入文档的字符数,并在到达“< mynode >”节点的开始和结束时存储该值。

然后我可以使用

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

4 回答 4

3

如果您使用的是IBM 的 Enterprise COBOL,那么您可以使用XML PARSE语句。解析器生成事件并填充可用于控制代码执行的特殊寄存器(由于某种原因,最后一个链接无法正常工作,它应该带您到该页面上的“控制流”标签)

如果您需要“修剪”树结构的某些部分,包括标记和数据,那么您可能需要解析原始结构,填充结构,并使用XML GENERATE来获取所需的 XML 数据流。解析器似乎不会告诉您每个事件发生在原始 XML 数据流中的位置,至少似乎没有一个特殊的寄存器填充该值。

于 2012-06-19T01:51:31.900 回答
2

COBOL XML PARSE 不提供位置信息 (AFAIK)。确定给定事件发生的偏移位置是不可能的。对感兴趣的标签进行文本搜索必然会导致大量问题 - 甚至不要考虑去那里......

我能想到的下一个可能性是在解析原始文档期间构造感兴趣的 XML 片段文档。片段完成后,将其写入您的 XML 数据库。

下面的示例程序说明了您可以如何去做。该程序采用 XML-SOURCE 文档并对其进行解析以查找感兴趣的事件(例如,“b”标签)。当找到这样的标签时,它开始构建一个片段文档(XML-FRAGMENT),直到找到结束标签。此时片段被输出并开始搜索下一个片段。

   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                            
       .                                       

此程序示例的输出为:

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

这不是您可能一直在寻找的单线解决方案,但您必须记住这是 COBOL!

于 2012-06-19T20:58:18.747 回答
1

在任何语言中,XML 解析都有点棘手。我建议为您的特定 COBOL 环境找到一个解析器库。 本文简要概述了 XML 解析领域。考虑一下您是否需要传递 XML 文件一次,在执行过程中提取所需的信息(SAX 方法适合您)或者是否要将 XML 加载到内存中并遍历其结构(您希望访问 DOM [文档对象模型])。

事实上,您的 COBOL 方言可能内置了 XML 支持(我的旧 COBOL 85 编译器没有),并带有XML PARSE语句。

这里有一些来自 Micro Focus 世界的信息

于 2012-06-18T18:25:04.380 回答
0

我现在的回复可能有点晚了,但我们使用Redvers COBOL XML 接口解析器,它具有“ASIS”功能,可将节点/父元素的全部内容读取到单个 COBOL 副本字段中 - 包含任何 XML 标记 -向上和从属元素。它是一个 DOM 样式解析器。生成器模块可以做相反的事情,使您能够将预先准备好的 XML 加载到实例文档中。

于 2017-01-19T14:59:39.960 回答