Chinaunix首页 | 论坛 | 博客
  • 博客访问: 273934
  • 博文数量: 18
  • 博客积分: 787
  • 博客等级: 军士长
  • 技术积分: 235
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-27 21:20
文章分类

全部博文(18)

文章存档

2015年(2)

2013年(2)

2012年(7)

2011年(1)

2010年(6)

分类: C/C++

2011-02-25 23:38:34

前言:最近因为某个项目,接触到jabberd2.0,在阅读源代码的过程中发现其中xml的解析部分完全使用了expat这个项目的API。下载了expatdoc/reference.html即是expatapi全解,全部英文讲解,没找到翻译的文档,索性自己翻译一个,拿出来供大家使用,水平有限,翻译不当的地方莫怪。接口太多,现把常用的或者说自己见过的翻译出来,其余的读者自行阅读英文文档。


Expat—API


构造解析器

XML_Parser XMLCALL

XML_ParserCreate(const XML_Char *encoding);
构造一个新的解析器。如果encoding非空,它为文档提供了一个特定的编码。这将覆盖将要解析的文档的编码声明。有四种内建的编码:
  • US-ASCII

  • UTF-8

  • UTF-16

  • ISO-8859-1

任何其他值都将触发对UnknownEncodingHandler函数的调用。


XML_Parser XMLCALL
XML_ParserCreateNS(const XML_Char *encoding, XML_Char sep);

构造一个能够处理名字空间的解析器。名字空间扩展了元素名和属性名,以URIsep(分隔符),和本地名称 级联的方式返回。这意味着你应该选一个不是合法URI组成部分的字符作为分隔符。当分隔符为空字符‘\0’时属于特殊情况:名字空间URI和本地名称没有分隔符—这是为了支持RDF处理器。


void XMLCALL
XML_ParserFree(XML_Parser p);

释放解析器使用的内存。你的应用程序将释放user_data使用的所有内存。


解析

陈述一个明显的事实:(sorry,以下的我竟然翻译不出来,贴英文了)

To state the obvious: the three parsing functions , and must not be called from within a handler unless they operate on a separate parser instance, that is, one that did not call the handler. For example, it is OK to call the parsing functions from within an XML_ExternalEntityRefHandler, if they apply to the parser created by .

Note: the len argument passed to these functions should be considerably less than the maximum value for an integer, as it could create an integer overflow situation if the added lengths of a buffer and the unprocessed portion of the previous buffer exceed the maximum integer value. Input data at the end of a buffer will remain unprocessed if it is part of an XML token for which the end is not part of that buffer.


enum XML_Status XMLCALL
XML_Parse(XML_Parser p, const char *s, int len, int isFinal);
enum XML_Status {

 
  XML_STATUS_ERROR = 0,
    
XML_STATUS_OK = 1
};

解析文档。字符串s包含部分(或者是全部)文档。len指示了s中的字节数。这意味中s不一定要以终结符结尾。这也意味着如果len大于了s指向的字符串长度,有可能出现内存错误。isFinal指示parser这是文档需要解析的最后一部分,通常,最后一块长度为0.如果出现错误,返回XML_STATUS_ERROR,否则返回 XML_STATUS_OK

enum XML_Status XMLCALL XML_ParseBuffer(XML_Parser p, int len, int isFinal);

这个同XML_Parse很像。除了一点,在这个函数中,expat提供数据buffer。通过使用函数获得数据缓冲区,应用程序可以避免输入数据的重复拷贝。


void * XMLCALL
XML_GetBuffer(XML_Parser p,
int len);

获得一个大小为len的缓冲区来读取一块数据。如果expat不能为buffer分配足够的空间,它将返回一个空字符。这将不得不再每次调用XML_ParseBuffer函数之前先调用这个函数。一个通常的用法像这样子:

for (;;) {
    int bytes_read;

    void *buff = XML_GetBuffer(p, BUFF_SIZE);

        if (buff == NULL) { /* handle error */ }
    bytes_read = read(docfd, buff, BUFF_SIZE);

    if (bytes_read < 0) {
/* handle error */ }
        if (! XML_ParseBuffer(p, bytes_read, bytes_read == 0)) { /* handle parse error */ }
    if (bytes_read == 0)
break;
}

enum XML_Status XMLCALL
XML_StopParser(XML_Parser p, XML_Bool resumable);
停止解析。导致 或者返回。(以下省略若干)

enum XML_Status XMLCALL

XML_ResumeParser(XML_Parser p);

当解析器被
XML_StopParser暂停之后,恢复解析。不可以再句柄被调用的时候 使用。返回值同。如果解析器当前没有被暂停,返回一个额外的错误值XML_ERROR_NOT_SUSPENDED. 附:此函数必须先被最深层嵌套的子解析器实例调用,当子解析器完成之后父解析器才会调用,然后递归调用直到整个文档解析器重启成功。意思是,父解析器不会自己恢复,直到应用程序在合适的时机调用
此函数为
Expat 1.95.8中新增。

void XMLCALL

XML_GetParsingStatus(XML_Parser p,
XML_ParsingStatus *status);
enum XML_Parsing {
    XML_INITIALIZED,

    XML_PARSING,

       
XML_FINISHED,
       
XML_SUSPENDED
};
typedef struct { enum XML_Parsing parsing; XML_Bool finalBuffer; } XML_ParsingStatus;
返回解析器的状态,包括初始化中,解析中,已结束或者暂停,以及最后的缓冲快是否正在被处理。参数
status不能为空。
expat 1.95.8中新增。

句柄(
handler)设置

尽管句柄通常在解析之前就被设置好而且不在改变,应用程序仍然有可能选择在解析的过程中改变句柄的设置。
例如,你的应用程序可能选择忽略所有从
para开始非降序排列的文本。一种实现方式为当一个para的开始标记出现的时候设置字符句柄,到达结束标记时取消句柄设置。通过给一个合适的句柄设置函数提供空指针,可能会取消句柄的设置。所有的句柄设置函数都没有返回值。你的句柄可能会收到 XML_Char类型组成的字符数组。按照条件不同,这种类型可能会被定义为char, wchar_t,或者unsigned short.前一个使用UTF-8编码,后两个使用UTF-16编码。需要注意你收到的字符编码格式与原来文本的字符编码是独立的,并不一定相同。

void XMLCALL
XML_SetStartElementHandler(XML_Parser p, XML_StartElementHandler start);
typedef void
(XMLCALL *XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts);
为开始(或者空)标记设置句柄(即处理函数)。属性以指向字符数组的指针的格式传递给开始标记处理函数。每个树形在数组中占用两个位置。属性名,后面随机跟随着属性值(如
type='set',atts[0]=”type”, atts[1]=”set”,类推)。这种成对的属性值以一个空指针结尾。注意一个空标记产生一个开始句柄和结束句柄的按顺序调用。

void XMLCALL
XML_SetEndElementHandler(XML_Parser p,
XML_EndElementHandler);
typedef void (XMLCALL *XML_EndElementHandler)(void *userData, const XML_Char *name);
设置结束标记处理函数(结束句柄),通上,一个空标记产生一个开始句柄的调用和一个结束句柄的调用。

void XMLCALL
XML_SetElementHandler(XML_Parser p, XML_StartElementHandler start, XML_EndElementHandler end);
通过一次调用,设置开始标记和结束标记的处理函数。


void XMLCALL

XML_SetCharacterDataHandler(XML_Parser p, XML_CharacterDataHandler charhndl)
typedef void
(XMLCALL *XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len);
设置文本处理句柄。你的句柄收到的字符串不是以空字符结尾。你不得不使用len参数来处理字符串的结尾。一块连续的不含xml标记的文本可能导致一系列对此句柄的调用。换句话说,如果你在文本中寻找特定的模式(如“abcd”,译者注),可以通过调用这个句柄来分割。注意:设置charhndl为空并不能立即终止调用,如果此时解析器正在处理这样的一块连续的无标记的文本块,因为解析器会继续调用直到到达文本块的结束。

void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser p,
XML_ProcessingInstructionHandler proc)
typedef void
(XMLCALL *XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data);
为处理说明设置句柄。
target参数为正在处理的说明中的第一个字符。Data参数为去掉所有的空格后的剩余字符。

void XMLCALL
XML_SetCommentHandler(XML_Parser p, XML_CommentHandler cmnt)
typedef void
(XMLCALL *XML_CommentHandler)(void *userData, const XML_Char *data);
为注释设置处理句柄。
Data为注释中的所有字符。

void XMLCALL
XML_SetStartCdataSectionHandler(XML_Parser p, XML_StartCdataSectionHandler start); typedef void (XMLCALL *XML_StartCdataSectionHandler)(void *userData);
设置一个句柄,将在一个
CDATA部分的开始被调用。

void XMLCALL
XML_SetEndCdataSectionHandler(XML_Parser p, XML_EndCdataSectionHandler end); typedef void (XMLCALL *XML_EndCdataSectionHandler)(void *userData);
 设置一个句柄,将在一个CDATA部分的结束处被调用。

void XMLCALL

XML_SetCdataSectionHandler(XML_Parser p,
XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end)
通过一次调用,同时设置
CDATA节的两个设置函数。

void XMLCALL XML_SetUnknownEncodingHandler(XML_Parser p, XML_UnknownEncodingHandler enchandler, void *encodingHandlerData)
typedef int (XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info);
typedef struct {

    int map[256];

       
void *data;
    int (XMLCALL *convert)(void *data, const char *s);

    void (XMLCALL *release)(void *data);

} XML_Encoding;

设置句柄处理内建集合之外(见上)的编码。这应该在
被调用之前完成。如果句柄知道如何处理 name对应的编码,它应该填充info并且返回XML_STATUS_OK.否则它应该返回XML_STATUS_ERROR。句柄在每个解析的实体上至多调用一次。可选的数据指针encodingHandlerData将会传回句柄。(略去 XML_Encoding的解释)

void XMLCALL

XML_SetStartNamespaceDeclHandler(XML_Parser p, XML_StartNamespaceDeclHandler start);
typedef void
(XMLCALL *XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri);
设置一个句柄,当一个名字空间(namespace)声明时被调用。名字空间声明出现在开始标记中。但是名字空间声明开始句柄(namespace declaration start handler)在开始标记句柄之前调用。

void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser p, XML_EndNamespaceDeclHandler end); typedef void (XMLCALL *XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix);
设置一个句柄,当离开名字空间的作用域时调用。每一个名字空间声明都会被调用,在结束标记的句柄调用之后。

void XMLCALL
XML_SetNamespaceDeclHandler(XML_Parser p, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end)

一个函数设置两个名字空间声明设置函数。

解析位置和错误报告函数

这些函数,当错误发生时你会调用,尽管位置报告函数在报告错误之外也很有用。位置报告是字节位置。

位置报告函数只有在DTD之外才精确。换句话说,在DTD声明处理函数之内调用通常不准。

enum XML_Error
XMLCALL
XML_GetErrorCode(XML_Parser p);

返回错误的类型。


const XML_LChar * XMLCALL XML_ErrorString(enum XML_Error code);
返回错误码对应
的错误说明。错误码应该是
返回的错误码之一。

其他函数


这一节的函数或者包含状态信息,或者可以动态设置解析选项。


void XMLCALL

XML_SetUserData(XML_Parser p,
void *userData);
这个函数设置传递
给句柄的用户数据指针。它重写此指针指向的以前数据。注意,当此函数调用完毕之后,释放
userData指向的空间是合理的。所以当已经有一个指针在哪里的时候,你调用函数,并且之后没有释放它关联的指针,你可能已经导致了内存泄
漏。


void * XMLCALL

XML_GetUserData(XML_Parser p);

这个函数返回传递给句柄
的指针。实际上它是以宏的方式实现的
阅读(4730) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~