Tuxedo 8.1 XML C++ Parser的使用[转帖]_MQ, Tuxedo及OLTP讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MQ, Tuxedo及OLTP讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4441 | 回复: 0   主题: Tuxedo 8.1 XML C++ Parser的使用[转帖]        下一篇 
luqunfang
注册用户
等级:少校
经验:1219
发帖:74
精华:0
注册:2012-6-25
状态:离线
发送短消息息给luqunfang 加好友    发送短消息息给luqunfang 发消息
发表于: IP:您无权察看 2012-7-12 11:06:13 | [全部帖] [楼主帖] 楼主

在TUXEDO 8.0中,客户机和服务器之间可以使用XML缓冲区进行数据交换,但由于8.0版本没有集成XML Parser,所以对XML的支持是有限的。从8.1版本开始,TUXEDO集成了Apache Xerces C++ Parser 1.7,这样服务器端就可以直接分析XML文档了,而不用再去调用其它XML Parser。
TUXEDO 8.1的samples中给了一个xmlstockapp例子,由于它太复杂(至少我这么认为),因此,本文将通过一个简单实用的例子来介绍XML缓冲区使用。

一.XML缓冲区的分配和传输
XML缓冲区支持的最大长度是4GB,分配方法与CARRAY缓冲区一样,需要指定长度。客户端需要打开一个XML文档,以字符方式读取文档内容,保存到缓冲区中,然后由tpcall()调用提交给服务进程。清单1-1是通信录应用程序的XML客户机代码段。

清单1-1 XML缓冲区客户机代码段,文件名:XML_cli.c

#define XMLDOCSIZE 1048576
... ...
FILE *xml_fd;
char *xml_buffer = NULL;
if ((xml_fd = fopen("friends.xml", "r")) != NULL) {
      xml_buffer = (char *)malloc(sizeof(char) * XMLDOCSIZE);
      nsize = fread(xml_buffer, sizeof(char), XMLDOCSIZE, xml_fd);
}
sendlen = nsize + 1; /* 实际读取的长度 */
if((sendbuf = (char *) tpalloc((char *)"XML", NULL, sendlen)) == NULL) {
      fprintf(stderr,"Error allocating send buffer, tperrno=%ld\n",tperrno);
      tpterm();
      return(1);
}
strncpy(sendbuf, xml_buffer, nsize);
ret = tpcall((char *)"ADD_FRIEND", (char *)sendbuf, sendlen, (char **)&rcvbuf, &rcvlen, TPNOTIME);
... ...


复制到缓冲区的XML文件必须遵循1.0标准,可以包含任何自定义的标记。本例中用到了friends.xml,这个文件包含了两条要添加到数据库好友信息,内容如清单1-2所示。

清单1-2 XML文件示例,文件名:friends.xml

<?xml version='1.0' encoding='UTF-8'?>
<friends>
<friend>
<friend_id>1</friend_id>
<fname>JQ</fname>
<fmobile>13910793488</fmobile>
</friend>
<friend>
<friend_id>2</friend_id>
<fname>Snna</fname>
<fmobile>13663129935</fmobile>
</friend>
</friends>


二.基于XML标记的DDR
XML缓冲区支持基于标记值的DDR,对于通信录应用程序来说,如果我们要把friend_id取值在1-10范围内的记录保存在table1中,把取值在11-20范围内的记录保存在table2中,把其它取值范围的记录保存在table3中,则可以在ubb配置文件中定义下面的路由标准来实现:

*ROUTING
symbol FIELD="friends/friend/ friend_id"
BUFTYPE="XML"
FIELDTYPE=LONG
RANGES="1-10:GROUP1,11-20:GROUP2,*:GROUP3"


XML缓冲区的路由字段还可以是STRING类型的,这时RANGES的取值必须用单引号引起来,请看如下代码段:

*ROUTING
symbol FIELD="stockquotes/stock_quote/symbol"
BUFTYPE="XML"
FIELDTYPE=STRING
RANGES="'BEAS'-'BEAS':GROUP1, 'MSFT'-'MSFT':GROUP2"


三.XML缓冲区的分析
服务器端收到XML缓冲区后,需要对它进行分析,从中取出标记值。Tuxedo 8.1集成了Apache Xerces C++ Parser 1.7,并提供了两种类型的分析器:SAX Parser和DOM Parser,服务器端通常使用DOM Parser,客户端通常使用SAX Parser。使用Xerces C++ Parser的步骤一般是:
· 初始化XMLC42系统;

 XMLPlatformUtils::Initialize();


· 根据XML缓冲区创建MemBufferInputSource;

 MemBufInputSource* memBufIS =
new MemBufInputSource( (const XMLByte*)xmlbuf, strlen(xmlbuf), bufId, false);


· 创建SAX Parser或DOM Parser;

 DOMParser *parser = new DOMParser;
SAXPArser *parser = new SAXParser;


· 对于SAX Parser,需要为文档和错误处理设置回调函数;

 SAXPrintHandlers handler;
parser->setDocumentHandler(&handler);
parser->setErrorHandler(&handler);


· 调用Xerces C++ Parser分析XML缓冲区;

 parse->parse(*memBufIS);


· 删除Parser和MemBufferInputSource;

 delete parser;
delete memBufIS;


· 退出XMLC42系统;

 XMLPlatformUtils::Terminate();


对于通信录应用程序来说,客户机给服务器传递了friends.xml文件,服务器端创建了一个DOM Parser对它进行分析,并把结果存入数据库,代码如清单1-3所示。

清单1-3 XML缓冲区的服务器代码,文件名:XML_serv.pc

#include <xercesc/parsers/DOMParser.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <atmi.h>
#include <userlog.h>
#include <stdlib.h>
#include <string.h>
char *localbuf=NULL;
static const char* bufId = "mybuf";
EXEC SQL begin declare section;
static long friend_id;
static char fname[10];
static char fmobile[14];
EXEC SQL end declare section;
EXEC SQL INCLUDE sqlca;
void TopTree( DOM_Node node);
void SubTree( DOM_Node node);
void parseXMLBuffer(char** xmlbuf);
#ifdef __cplusplus
extern "C"
#endif
void
#if defined(__STDC__) defined(__cplusplus)
ADD_FRIEND(TPSVCINFO *rqst)
#else
ADD_FRIEND(rqst)
TPSVCINFO *rqst;
#endif
{
      parseXMLBuffer(&rqstàdata);
      tpreturn(TPSUCCESS, 0, xmlbuf, rqstàlen, 0);
}
void parseXMLBuffer(char** xmlbuf)
{
      int errorCount ;
      localbuf = (char *)malloc(sizeof(char *) * 2048);
      XMLPlatformUtils::Initialize();
      MemBufInputSource* memBufIS =
      new MemBufInputSource( (const XMLByte*)*xmlbuf, strlen(*xmlbuf)-1, bufId, true);
      DOMParser *parser = new DOMParser;
      parseràparse(*memBufIS);
      if ((errorCount = parseràgetErrorCount()) == 0)
      {
            DOM_Document document = parseràgetDocument();
            DOM_Element topLevel = document.getDocumentElement();
            TopTree(topLevel);
      }
      delete parser;
      delete memBufIS;
      XMLPlatformUtils::Terminate();
}
void TopTree( DOM_Node node){
      if (node.getNodeType() == DOM_Node::ELEMENT_NODE)
      {
            if (node.getNodeName().equals ("friend")) SubTree(node);
            else
            {
                  DOM_NodeList children = node.getChildNodes();
                  for (int i=0; i<children.getLength(); i++) TopTree(children.item(i));
            }
      }
}
void SubTree( DOM_Node node)\
{
      DOM_NodeList children = node.getChildNodes();
      for (int i=0; i<children.getLength(); i++)
      {
            DOM_Node nod = children.item(i);
            if(nod.getNodeType()==DOM_Node::ELEMENT_NODE)
            {
                  if(nod.getNodeName().equals("friend_id"))
                  friend_id = atol(nod.getFirstChild().getNodeValue().transcode());
                  else if(nod.getNodeName().equals("fname"))
                  strcpy(fname, nod.getFirstChild().getNodeValue().transcode());
                  else if(nod.getNodeName().equals("fmobile"))
                  strcpy(fmobile, nod.getFirstChild().getNodeValue().transcode());
            }
      }
      EXEC SQL insert into FRIEND (FRIEND_ID,NAME,MOBILE)
      values (:friend_id, :fname, :fmobile);
      if (SQLCODE != SQL_OK) userlog("Cannot insert into FRIEND");
}


注意:服务器文件名为XML_serv.pc,先要使用esqlc命令对它作预编译,生成C源程序,然后把扩展名改为cpp,才能用buildserver来编译,原因是Xerces C++ Parser只提供了C++的编程接口。读者可以参考如下命令来编译:

proc iname=XML_serv.pc oname=XML_serv.cpp
buildserver -v -s ADD_FRIEND -f XML_serv.cpp -o XML_serv -f %TUXDIR%\lib\libtxml.lib


四.UBBConfigNT配置文件的编写
这个例子使用了Oracle8i数据库来测试,Tuxedo的配置文件如清单1-4所示。

清单1-4 Tuxedo的配置文件,文件名:UBBConfigNT

*RESOURCES
IPCKEY 123456
DOMAINID simpapp
MASTER SITE1
MAXACCESSERS 10
MAXSERVERS 5
MAXSERVICES 10
MODEL SHM
LDBAL N
*MACHINES
DEFAULT:
APPDIR="C:\TuxDAP\solutions\xml"
TUXCONFIG="C:\TuxDAP\solutions\xml\tuxconfig"
TUXDIR="G:\bea\tuxedo"
TLOGNAME=TLOG
TLOGDEVICE="C:\TuxDAP\solutions\xml\TLOG"
JQ LMID=SITE1
*GROUPS
DEFAULT: LMID=SITE1
GROUP1 LMID=simple GRPNO=1
OPENINFO="Oracle_XA:Oracle_XA+Acc=P/scott/tiger+SqlNet=oradb+SesTm=120+
MaxCur=5+LogDir=."
TMSNAME="TMS_ORA8i" TMSCOUNT=2
*SERVERS
DEFAULT: RESTART=Y MAXGEN=5 REPLYQ=Y CLOPT="-A"
XML_serv SRVGRP=GROUP1 SRVID=10
*SERVICES
ADD_FRIEND
*ROUTING


五.运行测试
执行XML_Cli.exe进行测试,friends.xml文件已经通过XML缓冲区成功地发送到服务器端;
打开SQL*PLUS,查看一下FRIEND表的内容,发现里面已经插入了两条记录,这两条记录的数据就是通过friends.xml文件来传输的!

本篇文章来源于 中间件技术社区(http://middleware123.com) 原文链接:http://middleware123.com/tuxedo/dev/30_3.html




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论