詞法特征:1)XML區分大小寫,如元素名在打開和關閉標記中應保持大小寫一致<mytag>…</mytag>,XML的保留詞串應符合大小寫要求<?XML …> <!ENTITY>…。
2)XML保留標記字符為:< > &,保留字符不允許出現在元素名、元素文本、屬性名、屬性值中,< 用戶打開標記,>用於關閉標記,&用於轉意,常見的轉意為 <生成<,>生成>,&生成&,&apos生成’,"生成”
3)元素名以下劃線或字母開始,可包含字母、數字、句點、連字符、下劃線、冒號和用於其他語言的擴展字符,元素名中不能有空格符(分格符、跳格符、換行符、回車符),元素名可以由名域前綴。如:<mytag> <dt:mytag> 元素文本可以是除XML保留字符外的字符集合,如<mytag> my money is $2000 </mytag>
4)屬性名的規則同元素名,屬性值由單引號或雙引號括約其中,可由除XML保留字符以外的字符串組成,如:<mytag myprop=”proper value”>。屬性名有xmlns前綴,表明該屬性定義了一個名域,如:<mytag XMLns:ns=”http://www.myweb.com/myschema”>
句法特征:1)XML文檔由一個XML說明、多個可選的文檔說明、多個可選的XML指令、多個可選的XML注釋和一個根元素的數據體組成,此外還可以有嵌入語句中的CDATA段,如:
<?xml …?> /*XML說明*/
<!DOCTYPE …> /*XML文檔說明*/
<!-- … --> /*XML注釋*/
<?xml-stylesheet …?> /*XML指令*/
<root> /*根數據元素*/
<child>
…<![CDATA[…]]>
</child>
</root>
2)XML說明由<?xml打開,由?>標關閉,其中包含版本、編碼等可選說明,如:<?XML version=”1.0” encoding=”UTF-9”?>
3)XML文檔說明由<!和保留串打開,由>關閉,如:<!DOCTYPE mydoc SYSTEM “mydoc.dtd”>
4)XML指令由<?和保留串打開,由?>關閉,如:<?XML-stylesheet type=”text/xsl” href=”mystyle.xsl”?>
5)XML注釋由<!――打開,由――>關閉,如:<!-- this is my XML document -->
6)XML元素由<元素名>打開,由/>,或</元素名>關閉,元素的打開和關閉標記相互匹配,如<myteg ../>或<mytag>…</myteg>,XML的元素允許嵌套,應此還應保持層次上的匹配,如<myteg><suBTag>..</subtag></mytag>。
7)CDTATA段由<![CDATA[>打開,由]]>關閉,用於使居於其中的語句規避XML解析規則。如:<![CDATA[ select * from mytable where thefIEld <= ‘100’ ]]>
根據以上的XML文法特征,可以構造出用於詞法分析的正則式和用於句法分析的下推自動機結構。
XML詞法正則式:
#define digit [1,2,…,9] /*數字字符*/
#define letter [a,b,…,z,A,B,…,Z] /*字母字符*/
#define signs [~, ! , @, #, %, ^, &,*,(, ), ?, :, ;, “, ‘, ,, ., /,-, _, +, =, , \] /*符號字符*/
#define ascii2 [0x80,…,0xFF] /*ASCII chart2 擴展字符*/
#define space [0x20, \t, \r, \n] /*空格符,跳格符,回車符,換行符*/
#define reserve [< , >, &] /*XML保留字符*/
1) 元素名的正則式:
element_name -> (_ letter ascii2) (ε _ - : . digit letter signs ascii2)*
2) 元素文本的正則式:
element_text -> (ε not reserve)*
3) 屬性名的正則式:
proper_name -> (_ letter ascii2) (ε _ - : . digit letter signs ascii2)*
4) 屬性文本的正則式:
proper_value -> (ε not reserve)*
XML句法結構:
xml_document -> xml_header (ε xml_declare xml_instrUCt xml_comments)* XML_element
xml_header -> [<?XML](space)*(proper_token)*(space)* [?>]
XML_declare -> [<!]reserve_Word(space)*(token)*(space)*[>]
XML_instruct -> [<?]reserve_Word(space)* (proper_token)* (space)*[?>]
XML_comments -> [<!--](ε digit letter signs ascii2 space)*[-- >]
XML_element -> [<]element_name (space)*( ε proper_token)*(space)*[/>]
[<]element_name(space)*( ε proper_token)*(space)*[>]
[ε <![CDATA[ ]element_text[ε ]]>]
(ε XML_element)*(space)*[</]element_name[>]
proper_token -> proper_name(space)*[=](space)* [ε <![CDATA[ ] [‘ “]proper_value[‘ “] [ε ]]>]
reserve_Word -> [DOCTYPE ELEMENT NOTATION …]
token -> (ε not reserve)*
分析XML文法需要構造一個下推自動機,它的結構定義如下:
1)STACK_DFA mata_XML_doc = <Q,Σ,σ,q,Γ,T,S >
Q: {…} /*詳見後面的狀態集合*/
Σ: /*指向待解析的XML元素詞串*/
σ: Q×Σ->Q /*狀態轉移函數,見狀態轉移列表*/
q: {NIL_SKIP} /*初始狀態*/
Γ: {NIL_FAILED,NIL_SUCCEED} /*終結狀態集合*/
S: {Q/*狀態*/, N/*DOM節點*/>,<…>} /*下推棧*/
2)棧頂符集合用於反映當前分析節點的類型:
T:{NIL/*空*/, TG/*標記*/, NS/*元素*/, IS/*指令*/, DS/*聲明*/, CD/*CDATA界段*/,CM/*注釋*/}
3)狀態集合反映了分析的某一階段特征,與棧頂符對應:
NIL: NIL_FAILED /*失敗*/
NIL_SKIP /*忽略*/
NIL_SUCCEED /*成功*/
CM: CM_BEGIN /*注釋開始*/
CM_END /*注釋結束*/
TG: TG_OPEN /*標記打開*/
TG_INT_CLOSE /*標記中斷*/
TG_PRE_CLOSE /*標記准備關閉*/
TG_CLOSE /*標記關閉*/
NS: NS_NAME_BEGIN /*元素名開始*/
NS_NAME_END /*元素名結束*/
NS_KEY_BEGIN /*屬性名開始*/
NS_KEY_END /*屬性名結束*/
NS_ASIGN /*屬性賦值*/
NS_VAL_BEGIN /*屬性值開始*/
NS_VAL_END /*屬性值結束*/
NS_TEXT_BEGIN /*元素文本開始*/
NS_TEXT_END /*元素文本結束*/
IS: IS_OPEN /*指令打開*/
IS_NAME_BEGIN /*指令名開始*/
IS_NAME_END /*指令名結束*/
IS_KEY_BEGIN /*指令鍵開始*/
IS_KEY_END /*指令鍵結束*/
IS_ASIGN /*賦值符*/
IS_VAL_BEGIN /*指令值開始*/
IS_VAL_END /*指令值結束*/
IS_CLOSE /*指令關閉*/
DS: DS_OPEN /*聲明打開*/
DS_SKIP /*越過申明節*/
DS_CLOSE /*聲明關閉*/
CD: CD_BEGIN /*CDATA界段開始*/
CD_END /*CDATA界段結束*/
4)棧頂動作:PUSH: 將當前節點和狀態壓入棧
POP:出棧並恢復當前節點和狀態
NOP:無棧操作
5)讀寫頭動作:NEXT: 移動至下一字符
SKIP: 越過轉義串或保留名串
PAUSE: 暫定於當前字符
STOP:停機於當前字符
6)狀態轉移列表:
說明: space 指符合空格定義的字符
name 指符合命名定義的字符
namepre 指符合命名的第一個字符
token 指除去保留字符外字符
other 指除去已判斷以外的字符
(狀態)輸入符(棧操作,狀態,讀寫頭動作)
(NOP,NIL_SKIP,NEXT)/*初始化*/
(NIL_SKIP)
space (NOP,NIL_SKIP,NEXT) /*忽略起始空格*/
< (NOP,TG_OPEN,NEXT) /*遇到標記*/
‘\0’ (NOP,NIL_SUCCEED,STOP) /*終結符*/
other (NOP,NIL_FAILED,STOP) /*無效字符*/
(TG_OPEN)
! (NOP,DS_OPEN,NEXT) /*遇到聲明符*/
? (NOP,IS_OPEN,NEXT) /*遇到指令符*/
/ (POP,TG_PRE_CLOSE,NEXT) /*准備關閉標記*/
namepre (NOP,NS_NAME_BEGIN,PAUSE) /*元素名開始*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(DS_OPEN)
other (NOP,DS_SKIP,PAUSE) /*忽略聲明*/
DS_SKIP)
> (NOP,DS_CLOSE,PAUSE) /*聲明結束*/
other (NOP,DS_SKIP,NEXT) /*忽略聲明*/
(DS_CLOSE)
> (NOP,TG_CLOSE,PAUSE) /*標記關閉*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(CM_BEGIN)
- (NOP,CM_END,SKIP) /*注釋開始*/
token (NOP,CM_BEGIN,NEXT) /*繼續注釋串*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(CM_END)
> (NOP,DS_CLOSE,PAUSE) /*注釋關閉*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(CD_BEGIN)
] (NOP,CD_END,SKIP) /*界段開始*/
token (NOP,CD_BEGIN,NEXT) /*繼續界段*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(CD_END)
> (NOP,DS_CLOSE,PAUSE) /*聲明關閉*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_OPEN)
namepre (NOP,IS_NAME_BEGIN,PAUSE) /*指令名開始*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_NAME_BEGIN)
space (NOP,IS_NAME_END,PAUSE) /*指令名結束*/
? (NOP,IS_NAME_END,PAUSE) /*指令名結束*/
& (NOP,IS_NAME_BEGIN,SKIP) /*字符轉義*/
name (NOP,IS_NAME_BEGIN,NEXT) /*繼續指令名*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_NAME_END)
space (NOP,IS_NAME_END,NEXT) /*忽略空格*/
? (NOP,IS_CLOSE,NEXT) /*標記中斷*/
namepre (NOP,IS_KEY_BEGIN,PAUSE) /*指令屬性名開始*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_KEY_BEGIN)
space (NOP,IS_KEY_END,PAUSE) /*屬性名結束*/
= (NOP,IS_KEY_END,PAUSE) /*屬性名結束*/
& (NOP,IS_KEY_BEGIN,SKIP) /*字符轉義*/
name (NOP,IS_KEY_BEGIN,NEXT) /*繼續屬性名*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_KEY_END)
space (NOP,IS_KEY_END,NEXT) /*忽略空格*/
= (NOP,IS_ASIGN,NEXT) /*屬性賦值符*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_ASIGN)
space (NOP,IS_ASIGN,NEXT) /*忽略空格*/
“ (NOP,IS_VAL_BEGIN,NEXT) /*屬性賦值打開*/
‘ (NOP,IS_VAL_BEGIN,NEXT) /*屬性賦值打開*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_VAL_BEGIN)
“ (NOP,IS_VAL_END,NEXT) /*屬性值結束*/
‘ (NOP,IS_VAL_END,NEXT) /*屬性值結束*/
& (NOP,IS_VAL_BEGIN,SKIP) /*字符轉義*/
token (NOP,IS_VAL_BEGIN,NEXT) /*繼續屬性值*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(IS_VAL_END)
space (NOP,IS_VAL_END,NEXT) /*忽略空格*/
? (NOP,IS_CLOSE,NEXT) /*標記中斷*/
other (NOP,IS_KEY_BEGIN,PAUSE) /*屬性名開始*/
(IS_CLOSE)
> (NOP,TG_CLOSE,NEXT) /*標記關閉*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_NAME_BEGIN)
space (NOP,NS_NAME_END,PAUSE) /*元素名結束*/
> (NOP,NS_NAME_END,PAUSE) /*元素名結束*/
/ (NOP,NS_NAME_END,PAUSE) /*元素名結束*/
& (NOP,NS_NAME_BEGIN,SKIP) /*字符轉義*/
name (NOP,NS_NAME_BEGIN,NEXT) /*元素名繼續*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_NAME_END)
space (NOP,NS_NAME_END,NEXT) /*忽略空格*/
> (NOP,TG_INT_CLOSE,NEXT) /*元素名結束*/
/ (NOP,TG_PRE_CLOSE,NEXT) /*元素名結束*/
other (NOP,NS_KEY_BEGIN,PAUSE) /*屬性名開始*/
(NS_KEY_BEGIN)
space (NOP,NS_NAME_END,PAUSE) /*屬性名結束*/
= (NOP,NS_KEY_END,PAUSE) /*屬性賦值符*/
& (NOP,NS_KEY_BEGIN,SKIP) /*字符轉義*/
name (NOP,NS_KEY_BEGIN,NEXT) /*繼續屬性名*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_KEY_END)
space (NOP,NS_KEY_END,NEXT) /*忽略空格*/
= (NOP,NS_ASIGN,NEXT) /*屬性賦值符*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_ASIGN)
space (NOP,NS_ASIGN,NEXT) /*忽略空格*/
“ (NOP,NS_VAL_BEGIN,NEXT) /*屬性賦值打開*/
‘ (NOP,NS_VAL_BEGIN,NEXT) /*屬性賦值打開*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_VAL_BEGIN)
“ (NOP,NS_VAL_END,NEXT) /*屬性值結束*/
‘ (NOP,NS_VAL_END,NEXT) /*屬性值結束*/
& (NOP,NS_VAL_BEGIN,SKIP) /*字符轉義*/
token (NOP,NS_VAL_BEGIN,NEXT) /*繼續屬性值*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_VAL_END)
space (NOP,NS_VAL_END,NEXT) /*忽略空格*/
> (NOP,TG_INT_CLOSE,NEXT) /*標記中斷*/
other (NOP,NS_KEY_BEGIN,PAUSE) /*屬性名開始*/
(TG_INT_CLOSE)
< (PUSH,TG_OPEN,NEXT) /*標記開始*/
other (NOP,NS_TEXT_BEGIN,PAUSE) /*元素文本開始*/
(NS_TEXT_BEGIN)
< (NOP,NS_TEXT_END,PAUSE) /*元素文本結束*/
& (NOP,NS_TEXT_BEGIN_BEGIN,SKIP) /*字符轉義*/
token (NOP,NS_TEXT_BEGIN,NEXT) /*繼續元素文本*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(NS_TEXT_END)
< (PUSH,TG_OPEN,NEXT) /*標記開始*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
(TG_PRE_CLOSE)
> (NOP,TG_CLOSE,PAUSE)/*標記結束*/
name (NOP,TG_PRE_CLOSE,NEXT) /*繼續關閉標記的元素名*/
other (NOP,NIL_FAILED,STOP) /*無效字符*/
(TG_CLOSE)
> (POP,NEXT) /*標記關閉,出棧*/
other (NOP,NIL_FAILED,STOP) /*非法字符*/
對XML聲明,本文只做了忽略處理,可以通過增加XML聲明的狀態和狀態轉移列表,進而支持XML聲明的分析。