电脑编程技巧与维护XML (可扩展标记语言)是WWW 联盟定义的元语言,已成为互连网数据交换的标准。
XML 具有广泛的用途,不仅被用于数据交换也经常被用于定义各种配置文件。
XML 文件只是以纯文本对数据进行编码的一种格式,使用XML 文件中所编码的数据之前,必须先将数据从纯文本中解析出来。
因此,XML 解析器在信息系统的构建过程中十分重要。
当前流行的XML 解析方法可以分为两类模型:SAX 和DOM 。
SAX 是一个用于处理XML 事件驱动的“推”模型,虽然它不是W3C 标准,但它却得到了广泛的认可。
SAX 解析器不像DOM 那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。
DOM 是以层次结构组织的节点或信息片断的集合,是一种基于树解析方法。
DOM 具有几个优点:由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构做更改;还可以在任何时候在树中上下导航,而不是像SAX 那样是一次性处理。
1XML 语法XML 文件中通常包含下列基本元素:标记名、属性名、属性值、文本值和各种定界符号如“<”,“>“等。
标记名和属性名是符合一定命名规则的字符串。
属性值和文本值可以是符合一定命名规则字符串,也可以是任意字符串。
例如语句<item name =“wang ”>example</item>中,“item ”是标记名,“name ”是属性名,“wang ”是属性值,“example ”是文本值。
由这些基本元素可以组成3类不同的句型。
句型1是由符号“<”、标记名、属性组(可选)、符号“>”组成,例如“<item>”、“<item name =“wang ”>”均为句型1。
句型2是由符号“<”、标记名、属性组、符号“/”、符号“>”组成,例如“<item name =“wang ”/>“为句型2。
句型3由符号“<”、符号“/”、标记名、符号“>”组成,例如“</item>”为句型3。
一个合法的XML 文件就是由上述3类句型和文本值按照特定句法组成的文本。
分别用A 、B 、C 表示句型1、句型1、句型3,用a 、b 、c 、d 表示标记名、属性名、属性值、文本值,用S 表示文档,用W 表示句子集合,用T 表示属性集,则XML 语法可用如下文法表示:1S =>AWC2W =>AWCW |BW |AdCW 3W =>AdC |B 4A =><a>|<aT>5B =><aT/>6C =></a>7T=>b=cT |b=c例如,给定如下的XML 文件,可得到图1语法树。
<xml><head><field name="id"length="6"/><field name="name"length="8"/></head>XML 解析器的设计与实现王克伟,胡立东(邳州市车辐中等专业学校,邳州221344)摘要:基于DOM XML 标准编程实现了一个解析器,可以从XML 文件中构造出一棵节点树,而后根据需要可以添加各种操作。
证明了解析器设计的正确性。
关键词:XML ;文法;解析器Design and Implementation of XML ParserWANG Kewei ,HU Lidong(CheFu Professional School of Pizhou City ,Pizhou 221344)Abstract :In the paper,a XML parser is realized based on DOM XML specification.It can constructs a XML tree from XMLfile.If needed,other operations on the XML tree can be added.It has been proved that the Parser design in the paper is valid.Key words :XML ;Grammar ;Parser作者简介:王克伟(1978-),男,硕士,研究方向:教育管理;胡立东(1980-),男,硕士,研究方向:数据库管理。
收稿日期:2010-10-10图138--SOFTWARE DEVELOPMENT AND DESIGN软件开发与设计<body><item><id>0001</id><name>aaaa</name></item><item></body></xml>解析器的任务是在检查XML 文件符合图1语法的情况下,得到图2的节点树2XML 解析器的设计在完成了XML 语法定义后,即可进行解析器的设计。
从上面文法定义的例子中可以看出,XML 解析器的任务并不是将XML 文件解析成一棵严格的语法树,而是在检查其符合语法的情况下将其解析成一棵节点树。
因此,XML 解析器的设计与一般程序语言的语法解析器设计可以有所不同。
在上述文法定义中,将定义式分为两组:定义式1、2、3用于文档的语法判别,即判别句型结构是否符合语法;定义式4、5、6、7用于句型的语法判别,即判别元素结构是否符合句型语法。
所设计的XML 解析器实质上是由两个自动机模型组成,它将XML 文件的解析操作分成两个层次完成。
第一层负责判断句型是否符合XML 语法并构造相应的节点树;第二层从XML 文件中解析出不同的句型提供给第一层。
图3是用于第二层解析不同句型的自动机模型,该自动机的初始状态为1,终结状态为5、10、12,分别对应解析出句型C 、A 、B 。
例如,输入串为“<xml>”时,状态转换过程为“1—>2—>6—>10”,输入串为“<field name ="id"length="6"/>”时,状态转换过程为“1—>2—>6—>7—>8—>9—>7—>8—>9—>11—>12”。
图4是用于第一层判别句型是否符合XML 语法的自动机模型。
虽然单独使用该自动机模型不能完成定义式1、2、3的语法检查,但附加一定的语义检查不仅可以实现语法检查功能,同时可以构造出相应的节点树。
3XML 解析器的实现为了构造图2的节点树,采用孩子兄弟链表来存储。
节点类的部分定义如下:class CXmlNode {public:void SetChild (CXmlNode*child);void SetParent (CXmlNode*parent);void SetBrother (CXmlNode*brother);…protected://指向第一个孩子节的指针CXmlNode*m_child;//指向兄弟节的指针CXmlNode*m_brother;//指向父节点的指针CXmlNode*m_parent;//节点标记名称char*m_tag;…};此外,还需定义一个解析器类来封装用户对解析器的访问,解析器类的部分定义如下:class CXmlParse {public:CXmlNode*Parse (char*xmlstr);…protected:int GetWord (char*&xmlstr);int GetSentence (char*&xmlstr);void Error ();…protected://当前句型标记名char*m_tag;//指向根节点的指针CXmlNode*m_root;//指向当前节点的指针CXmlNode*m_node;图2图3图439--…};下列代码是XML句型语法判别和节点树构造的简化了的C++实现。
CXmlNode*CXmlParse::Parse(char*xmlstr){int stat=0;CXmlNode*node=NULL;int sen=0;while((sen=GetSentence(xmlstr))!=SEN_ERROR){if(stat==0){if(sen==SEN_A){stat=1;node=new CXmlNode;node->SetTag(m_tag);m_root=node;m_node=node;continue;}Error();}if(stat==1){if(sen==SEN_A){node=new CXmlNode;node->SetTag(m_tag);if(m_node->Child()==NULL){m_node->SetChild(node);}else{node->Child()->AddBrother(node);node->SetParent(m_node);}node->SetParent(m_node);m_node=node;continue;}if(sen==SEN_B){node=new CXmlNode;node->SetTag(m_tag);if(m_node->Child()==NULL){m_node->SetChild(node);node->SetParent(m_node);}else{m_node->Child()->AddBrother(node);}m_node=node;continue;}if(sen==SEN_C){if(strcmp(m_node->Tag(),m_tag)){Error();return NULL;}m_node=m_node->Parent();if(m_node==NULL)continue;}Error();return NULL;}if(sen==WORD_D){stat=2;m_node->SetText(m_word);continue;}if(stat==2){if(sen==SEN_C){char*tag=m_node->Tag();if(strcmp(m_node->Tag(),m_tag)){Error();return NULL;}stat=1;m_node=m_node->Parent();continue;}Error();return NULL;}}return m_root}4结语尽管成熟的XML解析器已有多种,在此讨论了一种简化了的XML解析器设计和实现。