xml 词法解析 token的问题

问题描述

///我那样设计token结构可以么,书上解析编程语言时把括号都放进去了,但是感觉没用啊,所以我xml解析出来的全是节点值,不会有“<</>”这些的。而且也不是返回token而是返回tokenlist。这算词法分析吗usingSystem.Collections;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;enumTokenType{VERSION,//<??>STARTTAG,//<ENDTAG,//</COMMENT,NAME,VALUE,TEXT,CDATA}structtoken{publicstringStr;publicTokenTypeType;}enumState{BEGIAN,SATRTTAG,SATRTLB,ENDTAG,TEXT,//?>NAME,VALUE,CDATA,EQUALSIGN,COMMENT,//<!--VERSION,EQUAL,DOUBLEQUOTEVALUE,//双引号SIGNLEQUOTEVALUE,//单引号ENDVALUE,ERROR}classXmlAnalysis{privatestringmXmlText;privateDictionary<string,string>mVersion;privateboolmSyntax;publicXmlAnalysis(){mXmlText=string.Empty;mVersion=newDictionary<string,string>();mSyntax=true;}publicboolIsEmpty(){returnmSyntax;}publicvoidReadxml(stringxml){mXmlText=xml;}publicList<token>gettoken(stringXmlText){intindex=0;tokenTokenNode=newtoken();List<token>ListToken=newList<token>();Statestate=State.BEGIAN;StringBuildersb=newStringBuilder();boolFirstOrSecond=false;while(index<XmlText.Length){charc=XmlText[index];switch(state){caseState.BEGIAN://初始if(c=='<'){state=State.SATRTLB;}elseif(c==''||c=='n'||c=='r'||c=='t'){state=State.BEGIAN;}else{state=State.TEXT;}break;caseState.SATRTLB://开始switch(c){case'/':state=State.ENDTAG;break;case'?':state=State.VERSION;break;case'!':if(index+2<XmlText.Length&&XmlText[index+1]=='-'&&XmlText[index+2]=='-'){state=State.COMMENT;index+=2;}elseif(XmlText.Substring(index+1).StartsWith("[CDATA[")){state=State.CDATA;}else{state=State.ERROR;}break;default:if(char.IsLetter(c)){state=State.SATRTTAG;sb.Append(c);}else{Console.WriteLine("<后有不能识别的字符");state=State.ERROR;}break;}break;caseState.SATRTTAG://TAG的以后字符if(char.IsLetterOrDigit(c)||c=='_'||c=='-'){sb.Append(c);state=State.SATRTTAG;}else{switch(c){case'':Console.WriteLine(sb);state=State.NAME;TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.STARTTAG;ListToken.Add(TokenNode);break;case'>':Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.STARTTAG;ListToken.Add(TokenNode);state=State.TEXT;break;default:Console.WriteLine("标志元素存在不能识别的字符");state=State.ERROR;break;}sb.Remove(0,sb.Length);}break;caseState.TEXT:if(c=='<'){if(sb.Length>0){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.TEXT;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);}state=State.SATRTLB;}elseif(c=='&'){intnum=0;charReference=GetReference(XmlText.Substring(index+1),refnum);if(Reference!='0'){sb.Append(Reference);index+=num;}else{sb.Append(c);}}else{sb.Append(c);}break;caseState.ENDTAG:if(c=='>'){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.ENDTAG;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);state=State.BEGIAN;}elseif(char.IsLetterOrDigit(c)||c=='_'||c=='-'){sb.Append(c);}else{Console.WriteLine("结束文本出现");state=State.ERROR;}break;caseState.NAME:if(!FirstOrSecond&&char.IsLetter(c)){FirstOrSecond=true;sb.Append(c);}elseif(FirstOrSecond&&(char.IsLetterOrDigit(c)||c=='-'||c=='_')){sb.Append(c);}elseif(FirstOrSecond&&c==''){break;}elseif(c=='='){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.NAME;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);state=State.EQUALSIGN;}else{Console.WriteLine("属性名出错");state=State.ERROR;}break;caseState.EQUALSIGN:if(c==''){break;}elseif(c=='"'){state=State.DOUBLEQUOTEVALUE;}elseif(c=='''){state=State.SIGNLEQUOTEVALUE;}else{Console.WriteLine("属性出错");}break;caseState.DOUBLEQUOTEVALUE:if(c=='"'){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.VALUE;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);state=State.ENDVALUE;}elseif(!char.IsControl(c)){sb.Append(c);}else{Console.WriteLine("属性值出错");state=State.ERROR;}break;

解决方案

解决方案二:
caseState.ENDVALUE:if(c=='>'){state=State.TEXT;}elseif(c==''){state=State.NAME;}elseif(!char.IsControl(c)){sb.Append(c);}else{Console.WriteLine("属性后面出错");state=State.ERROR;}break;caseState.SIGNLEQUOTEVALUE:if(c=='''){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.VALUE;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);state=State.ENDVALUE;}elseif(!char.IsControl(c)){sb.Append(c);}else{Console.WriteLine("单引号后出错");state=State.ERROR;}break;caseState.VERSION:if(XmlText[index]=='?'&&XmlText[index+1]=='>'){Console.WriteLine(sb);sb.Remove(0,sb.Length);index+=1;state=State.BEGIAN;}else{sb.Append(c);}break;caseState.CDATA:if(index+2<XmlText.Length&&c==']'&&XmlText[index+1]==']'&&XmlText[index+2]=='>'){TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.CDATA;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);state=State.BEGIAN;index+=2;}else{sb.Append(c);}break;caseState.COMMENT:if(c=='-'){if(index+2<XmlText.Length&&XmlText[index+1]=='-'&&XmlText[index+2]=='>'){Console.WriteLine(sb);TokenNode.Str=sb.ToString();TokenNode.Type=TokenType.COMMENT;ListToken.Add(TokenNode);sb.Remove(0,sb.Length);index+=2;state=State.BEGIAN;}else{sb.Append(c);}}elseif(!char.IsControl(c)){sb.Append(c);}else{Console.WriteLine("注释出错");state=State.ERROR;}break;caseState.ERROR:Console.WriteLine("error");returnnull;default:Console.WriteLine("d");state=State.ERROR;break;}index++;}if(state==State.TEXT&&index==XmlText.Length&&sb.Length>0){Console.WriteLine(sb);sb.Remove(0,sb.Length);}returnListToken;}publiccharGetReference(stringStr,refintIndex){if(Str.StartsWith("lt;")){Index=3;return'<';}elseif(Str.StartsWith("gt;")){Index=3;return'>';}elseif(Str.StartsWith("amp;")){Index=4;return'&';}elseif(Str.StartsWith("apos;")){Index=5;return''';}elseif(Str.StartsWith("quot;")){Index=5;return'"';}else{return'0';}}}

解决方案三:
如果是写作业或者是练习,自己写词法分析是个不错的锻炼。如果是工作上用,要考虑用一些开源的项目,象GPLex等等。
解决方案四:
用递归方式应该比swtichcase方式可读性更好一些,也更符合xml的结构至于</>之类我建议保留,因为有可能一个xml的文档通过一些运算后,再存为xml文档,如果按你的做法,你还需要根据这些节点再构造一次xml.
解决方案五:
用有限状态机去解析xml网络上有很多例子啊,可以去参考下,看看你做的和别人做的有什么区别!googler
解决方案六:
引用2楼gomoku的回复:

如果是写作业或者是练习,自己写词法分析是个不错的锻炼。如果是工作上用,要考虑用一些开源的项目,象GPLex等等。

练习就在纠结token的设计思路对不对。
解决方案七:
引用3楼hdt的回复:

用递归方式应该比swtichcase方式可读性更好一些,也更符合xml的结构至于</>之类我建议保留,因为有可能一个xml的文档通过一些运算后,再存为xml文档,如果按你的做法,你还需要根据这些节点再构造一次xml.

递归就不能算词法分析了吧,必须用词法分析啊,而且如果保留</>这些,岂不是字符要回退.

时间: 2024-12-25 09:57:26

xml 词法解析 token的问题的相关文章

XML轻松学习手册(5)XML实例解析

xml 第五章:XML实例解析 提纲: 一:实例效果 二:实例解析 1.定义新标识. 2.建立XML文档. 3.建立相应的HTML文件. XML在不同领域有着广泛的应用,比如在科技领域的MathML,无线通信应用的WML,在网络图象方面的SVG等等,我们这里侧重讨论XML在web上的应用.XML在web上应用主要是利用其强大的数据操作能力.一般用XML配合javascript和asp等服务器端程序,可以实现网络上几乎所有的应用需求. 考虑讲解方便,我们在下面介绍一个简单的实例,不包含服务器端程序

java xml报文解析,把name名相同的解析成一个数组存到map集合

问题描述 java xml报文解析,把name名相同的解析成一个数组存到map集合 <?xml version="1.0" encoding="GBK"?> <request version="1.0"> <query> <filed name="FundOID" type="String"></filed> <filed name=&quo

XML和解析

XML和解析 1.什么是XML? Extensible Markup Language,可扩展标记语言. 一般也叫XML文档. 和JSON一样,也是常用的一种用于交互的数据格式. 2.XML语法 1)一个常见的XML文档一般由以下部分组成 1>文档声明: 在XML最前面,必须编写一个文档声明,用来声明XML文档的类型. 最简单的声明如:<?xml version='1.0'?> 2>元素(Element) 一个元素包括了开始标签和结束标签.<video>little y

xml解析-spring.xml如何解析,用dom4j及解析

问题描述 spring.xml如何解析,用dom4j及解析 解决方案 参考:http://blog.csdn.net/redarmy_chen/article/details/12969219 解决方案二: dom4j解析xmldom4j 解析 xmldom4j解析xml

struts2的validation.xml里解析正则表达式的问题

问题描述 我用java写了一个正则表达式.正则的规则是:只能是数字或者字母,但不能全部为数字publicclassTestRegx{publicvoidtest(Stringstr){booleanboo=str.matches("((\d)*)([a-zA-Z]+)((\d)*)([a-zA-Z]*)");System.out.println(boo);}publicstaticvoidmain(String[]args){TestRegxt=newTestRegx();t.test

xml-Android将PPT格式的XML数据解析,并实现演示

问题描述 Android将PPT格式的XML数据解析,并实现演示 Android从服务器获取由PPT转码成的XML数据,在手机端代码实现解析数据并实现播放PPT(不借助第三方演示工具),该如何实现!或者有什么好的想法,有什么支持技术,可以说出来,一起探讨一下!有过相关开发的,哪怕需求不太一样也希望能指点一二 解决方案 如果是xml数据解析之后,要实现播放效果,估计你自己得设定布局的样式和要展示的内容,要是手动来滑动的话,可以使用ViewPager控件来实现滑动的效果,也可以使用Handler消息

javascript-asp.net中如何把xml字符串解析成表格呈现在网页中?(最好有实现代码)

问题描述 asp.net中如何把xml字符串解析成表格呈现在网页中?(最好有实现代码) xml字符串名称为strResponseXml,内容如下: <?xml version='1.0'?>013海淀区0>343朝阳区3>783密云区7>9103海淀区9> 现想通过网页上的一个按钮事件把以上字符串解析成如下的表格形式:FID ID KIND NAME0 1 3 海淀区3 4 3 朝阳区7 8 3 密云区9 10 3 海淀区

Android平台基于Pull方式对XML文件解析与写入方法详解_Android

本文详细讲述了Android平台基于Pull方式对XML文件解析与写入方法.分享给大家供大家参考,具体如下: XML技术在跨平台的情况下的数据交互中得到了广泛的应用,假如我们需要开发一个Android应用程序,需要同服务器端进行数据交互,通过XML文件可以很方便的在Android平台和服务器之间进行数据传输,具体实现涉及到对XML文件进行解析及写入的技术.本文实现在Android平台上基于Pull方式对XML文件解析的技术. XmlPullParser是一个Java实现的开源API包(源码下载地

android编程之XML文件解析方法详解(附源码)_Android

本文实例讲述了android编程之XML文件解析方法.分享给大家供大家参考,具体如下: 在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. 今天解析的xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8