expat介紹文件翻譯

equalsai發表於2012-03-22


原文地址: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,就像從<stddef.h>定義為wchar_t一樣。傳送流給應用程式時,也是使用這種方式。當XML_UNICODE沒有被設定時,這個是設定XML_UNICODE。如果XML_UNICODE已經被設定了,但是不是設定的XML_UNICODE_WCHAR_T,然後UTF_16被儲存為unsigned short。

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 version="1.0" encoding="ISO-8859-2"?>

外部解析實體可能用一個文字宣告開始,這個看起來像一個XML宣告,但是隻有一個編碼宣告:

<?xml encoding="Big5"?>

對於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。有實體宣告的都有一個標記:

<!ENTITY logo SYSTEM "images/logo.gif" NDATA gif>

針對上邊的例子,實體名為“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


相關文章