1 DOM原理:
由于
XML
文件可以视为一个树型数据结构,
DOM
就是把这文档读到一棵树中,放到内存里,然后通过
DOM
提供的函数进行解析的一种
XML
解析方法。
2 DOM结点类型:
DOM
结点有以下几种类型,可以通过
XmlDomGetNodeType
()方法获得返回值(
int
)。
ELEMENT_NODE=1
ATTRIBUTE_NODE=2
TEXT_NODE=3
CDATA_SECTION_NODE=4
ENTITY_REFERENCE_NODE=5
ENTITY_NODE=6
PROCESSING_INSTRUCTION_NODE=7
COMMENT_NODE=8
DOCUMENT_NODE=9
DOCUMENT_TYPE_NODE=10
DOCUMENT_FRAGMENT_NODE=11
NOTATION_NODE=12
其中
1
和
3
为我们这里的常用类型。
3 DOM解析的步骤:
XmlCreate
():建立一个
XML CONTEXT
,这是
Oracle
的特有步骤。
/* Create a XML Context */
xctx = XmlCreate(&ecode, (oratext *)"XDEBUG", NULL);
if (xctx == NULL)
{
perror("XmlCreate");
return -1;
}
XmlLoadDom
():读取
XML
文件在内存中建立
DOM
树型结构。
/* Load DOM */
doc = XmlLoadDom(xctx, &ecode, "file", "test.xml", "discard_whitespace", TRUE, NULL);
if (doc == NULL)
{
perror("XmlLoadDom");
return -1;
}
XmlDomGetDocElem
():获得
XML
文件的根结点,这个结点一般都由发送和接收端末协商确定好,为了端末解析方便。例如:
<TableName>
/* Get root node */
root = XmlDomGetDocElem(xctx, doc);
if (root == NULL)
{
printf("No root node./n");
return -1;
}
接下来就是对具体
XML
文件中结点的解析过程了,这个过程通常用循环完成,例如:
for (i = XmlDomGetFirstChild(xctx, root); i != NULL; i = XmlDomGetNextSibling(xctx, i))
{
for (j = XmlDomGetFirstChild(xctx, i); j != NULL; j = XmlDomGetNextSibling(xctx, j))
{
text = XmlDomGetNodeName(xctx, j);
strcpy(name, text);
k = XmlDomGetFirstChild(xctx, j);
text = XmlDomGetNodeValue(xctx, k);
strcpy(value, text);
printf("%s: %s/n", name, value);
}
printf("/n");
}
4 DOM解析中的常用函数:
Ø
XmlDomGetFirstChild()
:取得某结点的第一个孩子结点。
Ø
XmlDomGetNextSibling()
:取得某结点的下一个孩子结点,直到返回
NULL
。
Ø
XmlDomGetNodeName()
:取得某结点的名字。
Ø
XmlDomGetNodeValue()
:取得某结点的值,只有
Attr, CDATA, Comment, ProcessingInstruction
和
Text nodes
可以取值。
5 DOM文件解析举例:
5.1 XML文件:
<TableName>
<row>
<ID>12345678</ID>
<WIN1>12345</WIN1>
<WIN2>00000</WIN2>
<PPT>1</PPT>
</row>
<row>
<ID>88888888</ID>
<WIN1>11111</WIN1>
<WIN2>22222</WIN2>
<PPT>2</PPT>
</row>
</TableName>
5.2 DOM解析代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <xml.h>
int main()
{
xmlctx *xctx; /* Xml Context */
xmlerr ecode; /* Error code */
xmldocnode *doc; /* Xml document node */
xmlnode *i, *j, *k; /* Temp node pointer */
xmlelemnode *root; /* Root node */
oratext *text; /* Temp string pointer */
/* Buffer */
char name[256];
char value[256];
/* Create a XML Context */
xctx = XmlCreate(&ecode, (oratext *)"XDEBUG", NULL);
if (xctx == NULL)
{
perror("XmlCreate");
return -1;
}
/* Load DOM */
doc = XmlLoadDom(xctx, &ecode, "file", "test.xml", "discard_whitespace", TRUE, NULL);
if (doc == NULL)
{
perror("XmlLoadDom");
return -1;
}
/* Get root node */
root = XmlDomGetDocElem(xctx, doc);
if (root == NULL)
{
printf("No root node./n");
return -1;
}
/* Get row node */
for (i = XmlDomGetFirstChild(xctx, root); i != NULL; i = XmlDomGetNextSibling(xctx, i))
{
/* Get database column */
for (j = XmlDomGetFirstChild(xctx, i); j != NULL; j = XmlDomGetNextSibling(xctx, j))
{
/* Get column name */
text = XmlDomGetNodeName(xctx, j);
strcpy(name, text);
/* Get value */
k = XmlDomGetFirstChild(xctx, j);
text = XmlDomGetNodeValue(xctx, k);
strcpy(value, text);
/* Print to stdout */
printf("%s: %s/n", name, value);
}
printf("/n");
}
return 0;
}
5.3 Makefile:
#################################################################
# PRIVATE PART #
#################################################################
# define global variables
EXE=$(HOME)/src/dai_weitao/xml_parse/test
OBJS=main.o
# include head file path
INC_DIR= -I$(HOME)/include
# include head file path( for proc )
PROC_INC= $(HOME)/include
# the library path
PROC_LIBS= $(LDPATHFLAG)$(LIBHOME) $(STATICPROLDLIBS) $(STATICPROLDLIBS)
LIBLIST=-lclntsh -lxml10
#MFLAGS= -g -DDEBUG -xarch=v9
MFLAGS= -g -DDEBUG -xarch=v9
MFLAGS= -g -DDEBUG -xarch=v9 -xarch=generic64
# define the target item
all: $(OBJS)
$(CC) $(MFLAGS) $(LFLAGS) -o $(EXE) $(INC_DIR) $(OBJS) -L$(ORACLE_HOME)/lib $(LIBLIST)
clean:
rm -f $(OBJS)
rm -f $(EXE)
#################################################################
# COMMON PART #
#################################################################
# include the precompiler part makefile
include $(ORACLE_HOME)/precomp/lib/env_precomp.mk
PROC_OPTION= PARSE=NONE LINES=YES CLOSE_ON_COMMIT=YES RELEASE_CURSOR=YES LTYPE=NONE CODE=ANSI_C
# suffixes rules
.SUFFIXES: .pc .c .o
.pc.c:
$(PROC) $(PROCFLAGS) $(PROC_OPTION) INCLUDE=$(PROC_INC) iname=$*
.pc.o:
$(PROC) $(PROCFLAGS) $(PROC_OPTION) INCLUDE=$(PROC_INC) iname=$*
$(CC) $(MFLAGS) $(CFLAGS) $(INC_DIR) -c $*.c
.c.o:
$(CC) $(MFLAGS) $(CFLAGS) $(INC_DIR) -c $*.c