解析xml的方法:通过libxml库解析XML文件方法



绪论
Libxml
个有免费许可用于处理XML、可以轻松跨越多个平台C语言库Libxml实现了读、创建及操纵XML数据功能
这个指南基于个简单XML应用

数据类型
Libxml
定义了许多数据类型它隐藏了杂乱来源以致你不必处理它除非你有特定需要xmlChar 替代char,使用UTF-8编码字节如果你数据使用其它编码它必须被转换到UTF-8才能使用libxmllibxml编码支持WEB页面有更多有关编码有用信息
XmlDoc
包含由解析文档建立树结构xmlDocPtr是指向这个结构指针
xmlNodePtr and xmlNode
包含单结点结构xmlNodePtr是指向这个结构指针它被用于遍历文档树

解析文档
解析文档时仅仅需要文件名并只并有检查
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
①定义解析文档指针
②定义结点指针(需要它为了在各个结点间移动)
④检查解析文档是否成功如果不成功libxml将指个注册并停止
注释
个常见是不适当编码XML标准文档除了用UTF-8UTF-16外还可用其它编码保存如果文档是这样libxml将自动地为你转换到UTF-8


⑤取得文档根元素
⑥检查确认当前文档中包含内容
⑦在这个例子中我们需要确认文档是正确类型Story”是在这个指南中使用文档根类型

取得元素内容
找到在文档树中要查找元素后可以取得它内容在这个例子中我们查找“story”元素进程将在冗长树中查找我们感兴趣元素我们假定期你已经有了个名为docxmlDocPtr个名为curxmlNodPtr
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur);
}
cur = cur->next;
}

①取得cur个子结点cur指向文档即“story”元素
②这个循环迭代通过“story子元素查找“storyinfo这是个包含有我们将查找keywords元素它使用了libxml串比较xmlStrcmp如果相符parseStory
void parseStory (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *key;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"keyword\"))) {
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
prf(\"keyword: %s\\n\", key);
xmlFree(key);
}
cur = cur->next;
}
;
}
再次取得第个子结点
像上面那个循环我们能过迭代查找我们感兴趣叫做“keyword元素
当我们找到元素“keyword”时我们需要打印它包含在XML记录内容文本被包含于元素子结点中因此我们借助了cur-> xmlChildrenNode为了取得文本我们使用xmlNodeListGetString它有个文档指针参数在这个例 子中我们仅仅打印它
注释
xmlNodeListGetString为它返回串分配内存你必须使用xmlFree释放它


使用XPath取得元素内容
除了步步遍历文档树查找元素外Libxml2包含支持使用Xpath表达式取得指定结点集完整Xpath API文档在这里Xpath允许通过路径文档搜索匹配指定条件结点在下面例子中我们搜索文档中所有keyword”元素
注释
下面是Xpath完整讨论它详细使用资料请查阅Xpath规范标准
这个例子完整代码参见附录DXPath例程代码
Using XPath requires ting up an xmlXPathContext and then supplying the XPath expression and the context to the xmlXPathEvalExpression

[Page]function.
The function s an xmlXPathObjectPtr, which s the of nodes satisfying the XPath expression.
使用XPath需要安装xmlXPathContext才支持XPath表达式及xmlXPathEvalExpression这个返回xmlXPathObjectPtr它包含有
XPath表达式结点集

xmlXPathObjectPtr
getnode (xmlDocPtr doc, xmlChar *xpath){
xmlXPathContextPtr context;
xmlXPathObjectPtr result;
context = xmlXPathNewContext(doc);
result = xmlXPathEvalExpression(xpath, context);
(xmlXPathNodeSetIsEmpty(result->nodeval)){
prf(\"No result\\n\");
NULL;
}
xmlXPathFreeContext(context);
result;
}
①首先定义变量
化变量context
③应用XPath表达式
④检查结果
返回xmlPathObjectPtr包含个结点集和其它需要被迭代及操作信息在这个例子中我们返回 xmlXPathObjectPtr我们使用它打印我们文档中keyword结点内容这个结点集对象包含在集合(nodeNr)元素数目及个结点(nodeTab)

for (i=0; i < node->nodeNr; i) {
keyword = xmlNodeListGetString(doc,
node->nodeTab[i]->xmlChildrenNode, prf(\"keyword: %s\\n\", keyword);


xmlFree(keyword);
}
①变量node->Nr持有结点集中元素数量我们使用它遍历
②打印每个结点包含内容
注释
Note that we are pring the child node of the node that is ed, because the contents of the keyword element are a child text node.
注意我们打印是结点子结点返回值keyword元素内容是个子文本结点

写元素
写元素内容使用上面许多步骤—解析文档并遍历树我们先解析文档然后遍历树查找我们想插入元素位置在这个例子中我们再次查找“storyinfo
”元素并插入keyword然后我们装文件写入磁盘完整代码:附录E添加keyword例程
本例中主要区别在于parseStory
void
parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
xmlNewTextChild (cur, NULL, \"keyword\", keyword);
;
}
XmlNewTextChild添加个当前结点子元素到树中
旦结点被添加我们应当写文档到文件中你是否想给元素指定个命名空间?你能添加它在我们例子中命名空间是NULL

xmlSaveFormatFile (docname, doc, 1);

个参数是写入文件你注意到和我们刚刚读入文件名是在这个例子中我们仅仅覆盖原来文件第 2个参数是xmlDoc结构指针第 3个参数设定为1保证在输出上写入

写属性
写属性类似于给个新元素写文本在这个例子中我们将添加reference结点URI属性到我们文档中referencestory元素个子结点所以找到并插入新元素及其属性是简单旦我们在parseDoc进行了检查我们将在正确位置加放我们新元素但进行的前我们需要定义个此前我们不见过数据类型

xmlAttrPtr attr;

我们也需要xmlNodePtr:
xmlNodePtr node;

剩下parseDoc则和前面检查根结点是否为story如果是那我们知道我们将在指定位置添加我们元素
node = xmlNewTextChild (cur, NULL, \"reference\", NULL);
attr = xmlNewProp (node, \"uri\", uri);

①使用xmlNewTextChild添国个新结点到当前结点位置
旦结点被添加文件应像前面例子将我们添加元素及文本内容写入磁盘



取得属性
取得属性值类似于前面我们取得个结点文本内容在这个例子中我们将取出我们在前部分添加URI
[Page]
这个例子步骤和前面是类似:解析文档查找你感兴趣元素然后进入完成指定请求任务在这个例子中我们getReference

void
getReference (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *uri;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"reference\"))) {
uri = xmlGetProp(cur, \"uri\");
prf(\"uri: %s\\n\", uri);
xmlFree(uri);
}
cur = cur->next;
}
;
}

关键xmlGetProp,它返回个包含属性值xmlChar在本例中我们仅仅打印它

注释
如果你使用DTD定义属性固定值或缺省值这个也将取得它

编码转换
数据编码兼容问题是员新建普通XML或特定XML时最常见困难按照这里
稍后讨论来研究设计你应用将帮助你避免这个困难实际上libxml能以UTF-8格式保存和操纵多种数据
使用其它数据格式比如常见ISO-8859-1编码必须使用libxml转换到UTF-8如果你想你以除UTF-8其它编码方式输出也必须做转换
如果能有效地转换数据Libxml将使用转换器无转换器时仅仅UTF-8UTF-16ISO-8859-1能够被作为外部格式使用有转换器时它能将从其它格式和UTF-8互换任何格式均可使用当前转换器支持大约150种区别编码格式的间相互转换实际支持格式数量正在被实现个实现在转换器尽可能支持每种格式

警告
个常见是在内部数据区别部分使用区别编码格式最常见是情况是个应用以ISO-8859-1作为内部数据格式结合libxml部分使用UTF-8格式结果是个应用要面对区别地内部数据格式部分代码执行后它或其它部分代码将使用曲解数据
这个例子构造个简单文档然后添加在命令行提供内容到根元素并使用适当编码将结果输出到标准输出设备上在这个例子中我们使用ISO-8859 -1编码在命令输入内容将被从ISO-8859-1

转换到UTF-8

包含在例子中转换使用libxmlxmlFindCharEncodingHandler

xmlCharEncodingHandlerPtr handler;
size = ()strlen(in)+1;
out_size = size*2-1;
out = malloc((size_t)out_size);

handler = xmlFindCharEncodingHandler(encoding);

handler->input(out, &out_size, in, &temp);

xmlSaveFormatFileEnc(\"-\", doc, encoding, 1);

①定义xmlCharEncodingHandler指针
XmlCharEncodingHandler需要给出输入和输出大小这里计算输入输出
XmlFindCharEncodingHandler使用数据编码作为参数搜索libxml已经完成转换器句柄并将找到指针返回如果没有找到则返回NULL
The conversion function identied by handler requires as its arguments poers to the input and output s, along with the length of each. The lengths must be determined separately by the application.
由句柄指定转换请求输入、输出中及它们长度作为参数这个长度必须由应用分别指定
⑤用指定编码而不是UTF-8输出我们使用xmlSaveFormatFileEnc指不定期编码方式

A.
编译
Libxml
包含个脚本xml2-config般用于编译和链接到库时产生标志
[Page]为了取得预处理和编译标志使用xml2-config cflags为了取得链接标志使用xml2-config libs其它有效参数请使用xml2-config help查阅

B.
举例文档
<?xml version=\"1.0\"?>
<story>
<storyinfo>
<author>John Fleck</author>
<datewritten>June 2, 2002</datewritten>
<keyword>example keyword</keyword>
</storyinfo>
<body>
<headline>This is the headline</headline>
<para>This is the body text.</para>
</body>
</story>
C. Keyword
例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
parseStory (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *key;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"keyword\"))) {


key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
prf(\"keyword: %s\\n\", key);
xmlFree(key);
}
cur = cur->next;
}
;
}
void
parseDoc(char *docname) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur);
}
cur = cur->next;
}
xmlFreeDoc(doc);
;
}

( argc, char **argv) {
char *docname;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
parseDoc (docname);
(1);
}

libxml( 3)
D. XPath
例程代码
# <libxml/parser.h>
# <libxml/xpath.h>
xmlDocPtr
getdoc (char *docname) {
xmlDocPtr doc;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
NULL;
}
doc;
}
xmlXPathObjectPtr
getnode (xmlDocPtr doc, xmlChar *xpath){
xmlXPathContextPtr context;
xmlXPathObjectPtr result;
context = xmlXPathNewContext(doc);
result = xmlXPathEvalExpression(xpath, context);
(xmlXPathNodeSetIsEmpty(result->nodeval)){
prf(\"No result\\n\");
NULL;
}
xmlXPathFreeContext(context);
result;
}

( argc, char **argv) {
char *docname;
xmlDocPtr doc;
xmlChar *xpath = (\"//keyword\");
xmlNodeSetPtr node;
xmlXPathObjectPtr result;
i;
xmlChar *keyword;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
doc = getdoc(docname);
result = getnode (doc, xpath);
(result) {
node = result->nodeval;
for (i=0; i < node->nodeNr; i) {
keyword = xmlNodeListGetString(doc, node->nodeTab[i]->prf

[Page](\"keyword: %s\\n\", keyword);
xmlFree(keyword);
}
xmlXPathFreeObject (result);
}
xmlFreeDoc(doc);
xmlCleanupParser;
(1);
}
E. 添加keyword例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
xmlNewTextChild (cur, NULL, \"keyword\", keyword);
;
}
xmlDocPtr
parseDoc(char *docname, char *keyword) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
(NULL);
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
(NULL);
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
(NULL);
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur, keyword);
}
cur = cur->next;
}
(doc);
}

( argc, char **argv) {
char *docname;
char *keyword;
xmlDocPtr doc;
(argc <= 2) {
prf(\"Usage: %s docname, keyword\\n\", argv[0]);
(0);
}
docname = argv[1];
keyword = argv[2];
doc = parseDoc (docname, keyword);
(doc != NULL) {
xmlSaveFormatFile (docname, doc, 0);
xmlFreeDoc(doc);
}
(1);
}
F.
添加属性例程代码


# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
xmlDocPtr
parseDoc(char *docname, char *uri) {
xmlDocPtr doc;
xmlNodePtr cur;
xmlNodePtr node;
xmlAttrPtr attr;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
(NULL);
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
(NULL);
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
(NULL);
}
node = xmlNewTextChild (cur, NULL, \"reference\", NULL);
attr = xmlNewProp (node, \"uri\", uri);
(doc);
}

( argc, char **argv) {
char *docname;
char *uri;
xmlDocPtr doc;
(argc <= 2) {
prf(\"Usage: %s docname, uri\\n\", argv[0]);
(0);
}
docname = argv[1];
uri = argv[2];
doc = parseDoc (docname, uri);
(doc != NULL) {
xmlSaveFormatFile (docname, doc, 1);
xmlFreeDoc(doc);
}
(1);
}
G.
取得属性值例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
getReference (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *uri;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"reference\"))) {
uri = xmlGetProp(cur, \"uri\");
prf(\"uri: %s\\n\", uri);
xmlFree(uri);
}
cur = cur->next;
}
;
}
void
parseDoc(char *docname) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
getReference (doc, cur);
xmlFreeDoc(doc);
;
}

( argc, char **argv) {
char *docname;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
parseDoc (docname);
(1);
}
H.
编码转换例程代码
# <.h>
# <libxml/parser.h>
unsigned char*
convert (unsigned char *in, char *encoding)
{
unsigned char *out;
ret,size,out_size,temp;
xmlCharEncodingHandlerPtr handler;
size = ()strlen(in)+1;
out_size = size*2-1;
out = malloc((size_t)out_size);
(out) {
handler = xmlFindCharEncodingHandler(encoding);
(!handler) {
free(out);
out = NULL;
}
}
(out) {
temp=size-1;
ret = handler->input(out, &out_size, in, &temp);
(ret || temp-size+1) {
(ret) {
prf(\"conversion wasn\'t successful.\\n\");
} {
prf(\"conversion wasn\'t successful. converted: }
free(out);
out = NULL;
} {
out = realloc(out,out_size+1);
out[out_size]=0; /*null terminating out*/
}
} {
prf(\"no mem\\n\");
}
(out);
}

( argc, char **argv) {
unsigned char *content, *out;
xmlDocPtr doc;
xmlNodePtr rootnode;
char *encoding = \"ISO-8859-1\";
(argc <= 1) {
prf(\"Usage: %s content\\n\", argv[0]);
(0);
}
content = argv[1];
out = convert(content, encoding);
doc = xmlNewDoc (\"1.0\");
rootnode = xmlNewDocNode(doc, NULL, (const xmlChar*)\"root\", out);
xmlDocSetRootElement(doc, rootnode);
xmlSaveFormatFileEnc(\"-\", doc, encoding, 1);
(1);
}
…………………………………………………………………………………………

[Page]char *convert(char *instr,char *encoding)
{
xmlCharEncodingHandlerPtr handler;
xmlBufferPtr in,out;

handler = xmlFindCharEncodingHandler(encoding);
(NULL != handler)
{
in = xmlBufferCreate;
xmlBufferWriteChar(in,instr);
out = xmlBufferCreate;
(xmlCharEncInFunc(handler, out, in)
0)


{
xmlBufferFree(in);
xmlBufferFree(out);
NULL;
}

{
xmlBufferFree(in);
(char *)out-
content;
}
}
}

Tags:  libxml2 libxml xml解析方法 解析xml的方法

延伸阅读

最新评论

发表评论