原文地址:http://www.xml.com/pub/a/1999/09/expat/index.html
因为需要用,所以才翻译了这个文档。但总归赖于英语水平很有限,翻译出来的中文有可能会词不达意。
什么是expat?
expat是一个库,用c实现的,用来解析XML文档。它是开源Mozilla工程的基本XML解析器,perl的XML::Parser以及其他开源的XML解析器。在(作者的)benchmark article中有展示。它有很高的可信度、鲁棒性和正确性。
这个库是James Clark创建的,他还创建了groff、jade、XP和XT。James同时还是在W3的XML撰写XML规格的工作小组中的技术Leader。从ftp://ftp.jclark.com/pub中的大多数包都是可用的,包括expat。还有一个test version,这是一个新特色,但是它和non-test version一样,都很健壮。这篇文章是基于test version而写的,版本是19990709
expat的概述:
expat是一个流导向(stream-oriented)的解析器。我们向解析器注册callback函数,然后开始传入被解析文档。对于解析器能够识别的文档部分,它会调用适当的handler解析那部分(如果你注册了的话)。被解析文档是分块传给解析器的,因此在你全部传入文档之前就开始解析。它同时还允许解析很大的文档,尽管这个文档不能完全放入整个内存。
expat是很惊人的,因为你能够设定很多种的handler和选项。但是你只需要四个函数就能做80%你想做的事儿。
XML_ParserCreate
创建一个新的解析器对象
XML_SetElementHandler
为开始和结束标签(tags)设置handler
XML_SetCharacterDataHandler
给字符串设置handler
XML_Parse
传送一个装满文档信息的buffer给解析器
这些函数和其他的函数在这个篇文章的参考部分都有描述。参考部分同时还详细描述了参数传送给不同类型的handlers.
这个压缩文件(zip file)里边包含这篇文章里边作为例子使用的makefile文件和源代码文件
让我们来看一个非常简单的示例程序,这段程序只使用了上边的三个函数。(它不需要设置字符串handler。)outline.c这个程序打印了一个元素(element)输出行,缩进的子元素(child elements)需要从包含他们的父元素(parent element)中区别出来。start handler完成了所有的工作,它给祖先元素(ancestot elements)的每一个层次打印两个缩进的空格,然后打印元素(element)和属性信息。最后自加加全局变量Depth。
int Depth;
void
start(void *data, const char *el, const char **attr) {
int i;
for (i = 0; i < Depth; i++)
printf(" ");
printf("%s", el);
for (i = 0; attr[i]; i += 2) {
printf(" %s='%s'", attr[i], attr[i + 1]);
}
printf("\n");
Depth++;
} /* End of start handler */
end 函数简单的做着记录工作,自减减Depth变量
void
end(void *data, const char *el) {
Depth--;
} /* End of end handler */
在创建了解析器以后,主函数将文档放进解析器,使解析器能够开始它的工作。
Building expat
使用expat的一个困扰是没有作为库的包,取而代之的是有四个分离的object files,我们不得不把他们链接到我们的应用程序。这个makefile能编译这篇文章里边介绍的简单的应用,可以作为一个模板。
编译时的附件条件
有一些编译时的宏,这些宏控制着被编译的expat的行为:
XML_UNICODE
内部使用UTF-16,在传送流给应用程序时,使用UTF-16代替UTF-8。这个改变了XML_char的定义,本来XML_char是被定义为char的。
XML_UNICODE_WCHAR_T
内部使用UTF-16,就像从
XML_DTD
包含代码来解析外部DTD
XML_NS
给词语检查命名空间
XML_BYTE_ORDER
对于小端对齐机器,给它设置“12”(机器对于第一字节有重要性最低),对于大端对齐机器,给它设置“21”(第一字节重要性最高)
XML_MIN_SIZE
使解析器比较小,一般的,运行也将比较慢
如果你的系统没有memmove函数,但是有bcopy函数,这种情况下,你将想要有一个宏,能够用bcopy重新定义memmove。有一个makefile宏能够实现这个功能,XP_MM。为了消除它的影响,你将不得不对于它的定义取消注释。
和expat工作
就像我在概述章节所提级的那样,文档是在某一时间分成块放入解析器的。每一个文档将被分成多少块,这个完全是由调用的应用程序决定的。有一个简单的示例程序,line。它在某一时间被分成一行传送给解析器,然后记录开始、结束、文字内容以及处理指令事件。通过交互输入文件到这个程序,你将开始获得直观的感受,对于解析器是怎样工作的。
纵观整个文档的层次结构,面向流的解析器需要一个良好的堆栈机制来跟踪当前的上下文。例如,回答一个减当的问题,“这些文字属于哪一个元素(element)?”需要一个栈,因为在遇到这些文字的路上,解析器可能已经下降到其他的元素(elements),这个元素是当前这个元素(element)的子元素(element)。
实际的情况是,你可能想要的是保持着一个栈,这个栈是里是当前的元素(element)和它的属性。你将这些信息在start handler中放入(push)栈中,然后在end handler中弹出(pop)栈。
对于一些任务,这是足以让信息保存在栈的什么深度(或者将会保存在,如果你有一个的话)。outline这个程序就是这个方面的一个例子。另外的一些其他的任务,将要跳过已经完成的元素(element)。当你看见元素(element)的的开始标签(start tag)的时候,你想要跳过它,你可以设置一个跳过flag(skip flag),记录从哪一个元素开始的深度,当结束标签handler(end tag handler)遇到相同的深度的时候,被跳过的元素(element)结束了,跳过flag可以被清空。如果你跟随惯例,根元素从1开始,这样你就可以对跳过flag和跳过深度使用相同的变量。
void
init_info(Parseinfo *info) {
info->skip = 0;
info->depth = 1;
/* Other initializations here */
} /* End of init_info */
void
rawstart(void *data, const char *el, const char **attr) {
Parseinfo *inf = (Parseinfo *) data;
if (! inf->skip) {
if (should_skip(inf, el, attr)) {
inf->skip = inf->depth;
}
else
start(inf, el, attr); /* This does rest of start handling */
}
inf->depth++;
} /* End of rawstart */
void
rawend(void *data, const char *el) {
Parseinfo *inf = (Parseinfo *) data;
inf->depth--;
if (! inf->skip)
end(inf, el); /* This does rest of end handling */
if (inf->skip == inf->depth)
inf->skip = 0;
} /* End rawend */
注意上边的那个例子,在start handler和end handler中,不同深度是如何被操作的。end tag handler是start tag handler的镜像。这是必要的,适当的模型控制。因为,在start tag handler中,我们在start tag 代码主体之后增加depth,然后在end handler中,我们需要在主体之前操作depth。如果我们决定将增加depth作为start handler的第一件事情,那么我们必须将减少depth作为end handler的最后一件事情。
handlers之间的通信
为了能够在不同的handlers之间在不使用全局变量的情况下能传送信息,我们需要定义一个数据结构保存住共享的变量。你能够告诉expat传送这个结构的一个指针给这个handlers。这个是很典型的,对于大多数handlers第一个参数。
命名空间处理
当解析器是使用XML_ParserCreateNS创建的时候,expat执行命名空间处理。在命名空间处理中,expat使用xmlns和xmlns:...属性,在他们发生时,给元素范围声明了命名空间。这就意味着你的start handler将不会看见这些属性。你的应用程序通过用XML_SetNamespaceDeclHandler设定命名空间声明handlers仍然能被他们的声明通知。
属于给定命名空间的元素类型和属性名在扩展形式中被传送给合适的handler。这个扩展形式是一个命名空间URI的连续,分隔字符(是XML_ParserCreateNS的第二个参数),以及本地名(冒号后的部分)。没有声明的名字前缀传不变的送给handler,前缀和冒号仍然链接着。无前缀的属性名不会被扩展,无前缀的属性名只有当他们在缺省的命名空间的范围的时候被扩展。
你能够使用XML_SetNamespaceDeclHandler函数给命名空间声明的开始和一个声明范围的结束设置handler。StartNamespaceDeclHandler在start标签handler之前被调用,并且EndNamespaceDeclHandler在对应的结束标签之前被调用,这个是为了结束命名空间的范围。命名空间的开始handler获得传过来的前缀和URI给命名空间。对于一个缺省的命名空间的定义(xmlns='...'),前缀为null。在缺省命名空间没有设定的地方,URI将为null。命名空间的结束handler获得关闭范围的前缀。
这些handlers被每一个声明调用。因此如果,例如,一个开始标签有三个命名空间声明,那么StartNamespaceDeclHandler在开始标签handler被调用之前将会被调用三次,每一次声明调用一次。
namespace.c这个例子展示使用了这些特性。像outline.c,它生成了一个输出行,但是另外,当一个命名空间范围开始和结束的时候,它给出了一个注解。这个例子也展示了使用应用程序的用户数据。
字符编码
如果XML是基于Unicode,并且每一个XML处理着都需要关注UTF-8和UTF-16(Unicode的一个或者是两个字节的编码),其他的编码可能在XML文档或者是实体中被声明。对于主文档,一个XML声明可能会包括一个编码声明:
外部解析实体可能用一个文本声明开始,这个看起来像一个XML声明,但是只有一个编码声明:
对于expat,在创建一个解析器的时候,你可能需要指定一个编码。当编码信息可能从一个外部文档源来的时候,这个是很有用的(像一个高层次的协议。)
在expat中有四个固定的编码格式:
* UTF-8
* UTF-16
* ISO-8859-1
* US-ASCII
任何在编码声明中被发现,或者是在解析器创建中协议编码被制定的时候,促使UnknownEncodingHandler被调用。这个handler获得传过来的编码名和一个XML_Encoding数据结构的指针。如果它知道怎样去处理这个编码格式的话。你的handler要填满这个结构体并且返回1。否则,这个handler将会返回0。这个handler同样获得一个选择应用数据结构的指针。当你设置handler的时候,你可能会指出。
expat在字符编码上的限制,这个通过填满XML_Encoding结构体能够支持。包括文件:
1.每一个ASCII字符,能够在一个良好形式的XML文档显示,必须通过一个单字节被表示,并且这个字节必须与它的ASCII编码相符(除了$@\^'{}~这些字符)
2.字符必须是使用四字节或者更少的编码。
3.所有的字符被编码,必须有Unicode值,小于或者等于65535(0xFFFF),这个不适用于固定支持的UTF-16和UTF-8。
4.没有字符可能通过更多的一个明显的字节序列被编码。
xml_encoding包含一个整数数组对应的第一字节的编码序列。如果该值在数组中的一个字节是零或正,然后字节是一个单字节编码,在数组中包含编码Unicode标量值。A -1在这个数组中指出了一个畸形字节。如果这个值是-2、-3或者是-4,那么这个字节是各自2、3或4字节序列的开始。多字节序列会被传送给转化函数,在XML_Encoding数组中被指出。这个函数会返回序列的Unicode标量值或者是-1,如果这个序列是急性的话。
对于expat使用者,一个隐藏的陷阱要注意。可能会陷入因为expat可以接受输入可变的编码,但是传给handlers的字符串总是UTF-8编码。你的应用程序要为任何字符串转化为其他编码形式负责。
处理外部实体参照
expat不会直接读取或者解析外部实体。请注意,任何外部DTD都是外部实体的一个特殊case。如果没有设置ExternalEntityRefHandler,那么外部实体参照会被忽略。否则,它会调用你的handler,使用读取和解析外部实体需要的信息。
你的handler对于解析实体没有直接关系,但是对于使用XML_ExternalEntityParserCreate创建一个最基本的解析器是有关系的。这个会返回一个XML_Parser实例(instance),这个实例有handlers和其他从父解析器被初始化的数据结构。你可能接着会使用XML_Parse或者是XML_ParseBuffer调用这个解析器。因为外部实体我们还会涉及其他的外部实体,你的handler也许需要准备被递归调用。
解析DTDs
为了解析参数实体,当expat被编译的时候,XML_DTD宏必须被定义。除此以外,创建解析器后,并且开始解析之前,你必须调用XML_SetParamEntityParsing,并且使用下边的参数:
XML_PARAM_ENTITY_PARSING_NEVER
不解析参数实体或者外部子集
XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
解析参数实体和外部子集,除非standalone在XML定义时被设置为"yes"。
XML_PARAM_ENTITY_PARSING_ALWAYS
总是解析参数实体和外部子集
为了能够读取外部子集,你必须想上边描述的那样设置一个外部实体参照handler。
expat函数参考
解析器的创建
XML_ParserCreate
XML_Parser XML_ParserCreate(const XML_Char*encoding)
创建一个新的解析器,如果encoding为不为null,指定一个字符编码给文档使用。这个会无视文档声明的编码形式。有四种固定的编码形式:
US-ASCII
UTF-8
UTF-16
ISO-8859-1
其他值将会引起UnknownEncodingHandler的调用
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_ParserCreateNS
XML_Parser XML_ParserCreateNS(const XML_Char*encoding, XML_Char sep)
创建一个新的解析器,这个解析器有命名空间有效的处理。命名空间扩展了元素名和属性名返回作为一个连续的命名空间URI、sep、以及本地名字的一部分。这就意味着你应该指定一个字符作为sep,它不能作为有效URI的一部分。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_ExternalEntityParserCreate
XML_Parser XML_ExternalEntityParserCreate(XML_Parser p, const XML_Char *context, const XML_Char *encoding)
创建一个新的XML_parser对象,解析一个外部实体。上下文是上下文参数传递,通过调用一个ExternalEntityRefHandler函数。其他的状态信息,譬如handlers、用户数据、命名空间处理都是从解析器继承得来的,通过第一个参数传递。在这个解析器中,因此你没有必要去调用任何行为改变函数(除非你想这个解析器有和父解析器不同的行为)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_ParserFree
void XML_ParserFree(XML_Parser p)
释放解析器使用的内存。你的应用程序负责释放所有和UserData有关联的内存。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
解析
XML_Parse
int XML_Parse(XML_Parser p, const char *s, int len, int isFinal)
解析文档。string s是一个buffer,包含文档的一部分(也许是全部)。s的字节数,也就是文档的一部分,是由len指出来的。这也就意味着,s为Null要被终止。同时也意味着,如果len比内存中s所指向的块字节数大,可能有一个内存错误。isFinal参数通知解析器,这是文档的最后一块。通常,最后一块是空(i.e len为0)。如果出现语法错误,返回0。否则返回一个非零的值。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_ParseBuffer
int XML_ParseBuffer(XML_Parser p, int len, int isFinal)
这个函数类似XML_Parser,除了在这个函数中,expat提供了buffer。通过从expat的XML_GetBuffer函数获得buffer,应用程序能避免两次复制输入。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetBuffer
void *XML_GetBuffer(XML_Parser p, int len)
获得一个大小为len的buffer,将文档的一块放到这个buffer中。如果expat不能分配足够的内存空间给buffer,返回NULL值。每一次调用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;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
handler设定
虽然通常handlers设置在解析之前,并且是单独的。但是一个应用程序可能选择设置或者更改这个正在进展的解析事件的handler。例如,你的应用程序也许会选择忽略所有的文本,不是起源于同一个**元素(a para element)。一种方式是当开始标签被看见的时候设置字符handler,并且不设定和它对应的结束标签(end tag)。
一个handler也可以不设定,通过提供一个空指针给设定handler的函数。设置handler为空的函数有返回值。
你的handlers将会需要传入字符串,通过XML_char类型的数组。这个类型定义在xmlparse.h,并且有条件设定是XML_UNICODE宏中的任意一个。如果一个也没有设定,那么XML_char包含的字符就是UTF_8编码。否则你将需要传入UTF_16当形式是unsigned short或者是wchar_t字符的时候。
请注意,你将会收到文档的最初编码的形式不支持。在这个文档的其他地方,关于这一点我可能简单的提及UTF_8。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetElementHandler
XML_SetElementHandler(XML_Parser p,
XML_StartElementHandler start,
XML_EndElementHandler end);
typedef void
(*XML_StartElementHandler)(void *userData,
const XML_Char *name,
const XML_Char **atts);
typedef void
(*XML_EndElementHandler)(void *userData,
const XML_Char *name);
设置开始和结束标签的handlers。属性通过一个char类型的向量指针被传给开始handlers。每一个属性在start标签的这个向量中占据2个连续的空间:属性名跟随着属性值。如果有空指针,这两个handlers都终止。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetCharacterDataHandler
XML_SetCharacterDataHandler(XML_Parser p,
XML_CharacterDataHandler charhndl)
typedef void
(*XML_CharacterDataHandler)(void *userData,
const XML_Char *s,
int len);
设置一个文本handler。你的handler接受到的这个字符串不是空,否则终止。你需要使用长度参数去处理字符串的结束。单个相邻的文本块将导致连续的调用到这个handler。换句话说,如果在一个文本总搜寻一个模板,可能会被分裂交叉的调用这个handler。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetProcessingInstructionHandler
XML_SetProcessingInstructionHandler(XML_Parser p,
XML_ProcessingInstructionHandler proc)
typedef void
(*XML_ProcessingInstructionHandler)(void *userData,
const XML_Char *target,
const XML_Char *data);
设置一个处理指示的handler。target是第一个单词,在处理指示中。data是它里边的在跳过所有的空格字符后的初始单词后的其他字符。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetCommentHandler
XML_SetCommentHandler (XML_Parser p,
XML_CommentHandler cmnt)
typedef void
(*XML_CommentHandler)(void *userData,
const XML_Char *data);
设置一个处理注释的handler。data是所有注释中的文字分隔符
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetCdataSectionHandler
XML_SetCdataSectionHandler(XML_Parser p,
XML_StartCdataSectionHandler start,
XML_EndCdataSectionHandler end)
typedef void
(*XML_StartCdataSectionHandler)(void *userData);
typedef void
(*XML_EndCdataSectionHandler)(void *userData);
设置获得调用一个CDATA段的开始和结束处理的handlers
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetDefaultHandler
XML_SetDefaultHandler(XML_Parser p,
XML_DefaultHandler hndl)
typedef void
(*XML_DefaultHandler)(void *userData,
const XML_Char *s,
int len);
设置一个处理文档中所有不能被处理的字符的handler。这个既包括没有设置handler不能被处理的字符(像一些DTD声明的类型),也包括那些能够被描述的数据,但是他们当前没有设定handler。请注意,一个连续的数据块,是注定要被描述的,默认的handler可能实际上会被调用多次。给这个函数设置handler有副作用,会关闭内部定义的实体的参考的扩展。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetDefaultHandlerExpand
XML_SetDefaultHandlerExpand(XML_Parser p,
XML_DefaultHandler hndl)
设置一个缺省handler,但是不影响内部实体定义的扩展。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetExternalEntityRefHandler
XML_SetExternalEntityRefHandler(XML_Parser p,
XML_ExternalEntityRefHandler hndl)
typedef int
(*XML_ExternalEntityRefHandler)(XML_Parser parser,
const XML_Char *context,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
设置一个扩展实体定义的handler。这个handler同会被处理外部扩展DTD子集的处理调用,如果参数实体解析有效的话。(参看XML_SetParamEntityParsing)
base:用于系统标识符,被XML_SetBase设定,有可能为NULL
publicId: 在实体声明的时候被赋值,有可能为NULL
systemId: 系统标识符,实体声明时指定,肯定不为NULL
这个handler有多个方面与其他的handlers不同。首先,这个handler返回一个整数。如果成功进行了扩展实体定义的处理则一个非零的值被返回。返回零标识出错,并且致使调用的解析器返回一个XML_ERROR_EXTERNAL_ENTITY_HANDLING的错误。
第二,取代了第一个参数为userData,它面对实体定义时从解析器获得。这样,接下来的上下文参数,可以作为参数去调用XML_ExternalEntityParserCreate。使用被返回的解析器,外部实体的主体能被递归解析。
因为这个handler可能被递归,因此不应该将信息保存到全局变量或静态变量。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetUnknownEncodingHandler
XML_SetUnknownEncodingHandler(XML_Parser p,
XML_UnknownEncodingHandler enchandler,
void *encodingHandlerData)
typedef int
(*XML_UnknownEncodingHandler)(void *encodingHandlerData,
const XML_Char *name,
XML_Encoding *info);
设置一个handler去处理编码区别于固定的设定。如果handler知道怎样去处理被给出的名字的编码,它将填满信息数据结构体并且返回1。否则返回0。
typedef struct {
int map[256];
void *data;
int (*convert)(void *data, const char *s);
void (*release)(void *data);
} XML_Encoding;
map数组包括为每一个在字节序列中的主要的字节信息。如果相同的值是>=0,它是一个单字节序列并且字节编码是Unicode编码。如果值是-1,那么那个字节在序列中作为起始字节是无效的。如果值是-n,这里的n是一个整数值>1,那么n是序列中的字节数并且实际上转化已经通过convert指向的那个函数完成。如果这个序列自身无效的话这个函数可能返回-1。如果只要单一字节编码,那么这个convert指针有可能为null。data参数给convert函数传送XML_Encoding的数据指针。字符串s非空并且指向的字节序列被转化。
当它完成编码的时候,这个函数指向release,被解析器调用。它可能为null。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetNamespaceDeclHandler
XML_SetNamespaceDeclHandler(XML_Parser p,
XML_StartNamespaceDeclHandler start,
XML_EndNamespaceDeclHandler end)
typedef void
(*XML_StartNamespaceDeclHandler)(void *userData,
const XML_Char *prefix,
const XML_Char *uri);
typedef void
(*XML_EndNamespaceDeclHandler)(void *userData,
const XML_Char *prefix);
给命名空间声明设定handler。命名空间声明发生在start标签(start tags)内。但是命名空间声明开始handler在开始标签handler中已经被声明的每一个命名空间之前被调。对应的命名空间的结束handler在命名空间被关联的元素结束标签之后被调。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetUnparsedEntityDeclHandler
XML_SetUnparsedEntityDeclHandler(XML_Parser p,
XML_UnparsedEntityDeclHandler h)
typedef void
(*XML_UnparsedEntityDeclHandler)(void *userData,
const XML_Char *entityName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName);
设置一个接受没有被解析的实体的声明的handler。有实体声明的都有一个标记:
针对上边的例子,实体名为“logo”,systemId是“images/logo.gif”并且标记名为“gig”。对于这个例子,publicId参数为Null。base参数为XML_SetBase设置的内容。如果没有设置,那么为null。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetNotationDeclHandler
XML_SetNotationDeclHandler(XML_Parser p,
XML_NotationDeclHandler h)
typedef void
(*XML_NotationDeclHandler)(void *userData,
const XML_Char *notationName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
设置接受标记声明的handler。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetNotStandaloneHandler
XML_SetNotStandaloneHandler(XML_Parser p,
XML_NotStandaloneHandler h)
typedef int
(*XML_NotStandaloneHandler)(void *userData);
设置一个handler,如果文档不是“standalone”,就被调用。这个发生在当有一个外部子集或者是有一个针对参数实体的关联,但是在xml声明时,没有给"standalone"设置为“yes”。如果这个handler返回0,那么这个解析器将抛出一个XML_ERROR_NOT_STANDALONE的错误。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
解析位置和错误报告函数
当解析函数返回0的时候,有一些函数你可能想去调,因为对于一些错误,报告错误位置的函数是挺有用的。位置报告是字符串序列生成的第一个当前事件(或者说,错误是导致解析函数返回0的原因。)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetErrorCode
enum XML_Error XML_GetErrorCode(XML_Parser p)
返回发生了那种类型的错误
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_ErrorString
const XML_LChar *XML_ErrorString(int code)
返回一个字符串,描述对应code的错误。这个code是一个枚举值,能够从XML_GetErrorCode中被返回。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetCurrentByteIndex
long XML_GetCurrentByteIndex(XML_Parser p)
返回位置的偏移字节。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetCurrentLineNumber
int XML_GetCurrentLineNumber(XML_Parser p)
返回位置的行号。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetCurrentColumnNumber
int XML_GetCurrentColumnNumber(XML_Parser p)
返回偏移,从当前行的开始位置。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Miscellaneous functions
这些函数在这部分,或者能从解析器获得状态信息,或者能被使用来动态设置解析器选项。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetUserData
XML_SetUserData(XML_Parser p, void *userData)
设置用户数据指针,获得的传送给handlers。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetUserData
void * XML_GetUserData(XML_Parser p)
返回用户数据指针,获得的传送给handlers。它实际上是用一个宏实现的。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_UseParserAsHandlerArg
void XML_UseParserAsHandlerArg(XML_Parser p)
这个被调用以后,在userData参数中,handlers获得解析器。使用上边的XML_GetUserData函数,userData信息能够一直被获得。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetBase
int XML_SetBase(XML_Parser p, const XML_Char *base)
设置base,这个base被用来解决在系统标识符中依赖URIs。如果没有内存存储base,返回0,否则返回非0。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetBase
const XML_Char * XML_GetBase(XML_Parser p)
返回base,为了解决URIs依赖
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_GetSpecifiedAttributeCount
int XML_GetSpecifiedAttributeCount(XML_Parser p)
当属性被记录到starthandler的atts向量(the atts vector)中的时候,属性肯定被设定在元素中,所有属性从ATTLIST申明的缺省信息中获得他们的值。这个函数返回属性数,属性数肯定被设置了,因此给出缺省设置的针对第一个属性的偏移。它提供信息给最后调用的start handler。如果你在start handler中,那么意味着当前调用。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetEncoding
int XML_SetEncoding(XML_Parser p, const XML_Char *encoding)
设置被解析器使用的编码(encoding)。这个与给创建解析器的函数传入一个非空的encoding参数是等效的。它不能在XML_Parser后被调用或者是XML_ParseBuffer在解析器中已经被调用。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XML_SetParamEntityParsing
int XML_SetParamEntityParsing(XML_Parser p, enum XML_ParamEntityParsing code)
如果解析器不在XML_DTD被设置的时候编译,那么这个函数返回0.否则返回1并且允许参数实体的解析,包括在外部DTD子集的外部参数实体。根据代码,给代码的选择是:
* XML_PARAM_ENTITY_PARSING_NEVER
* XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
* XML_PARAM_ENTITY_PARSING_ALWAYS