随笔-341  评论-2670  文章-0  trackbacks-0
    为了纪念自己为了明天的XML考试复习了半天,特地根据MSDN描述的标准做了一个XML的解释器。接口类似DOM和SAX的混合体。
    目前什么都不支持,不过以后打算做完DTD和XPath。XSD和XSL就先算了。反正是写着玩的。把代码贴出来先。这个代码使用了自己开发的一套C++基础库。

    接口:
  1 /*******************************************************************************
  2 Vczh Library++ 2.0
  3 XML
  4 开发者:陈梓瀚
  5 
  6 接口:
  7 类:
  8 函数:
  9 *******************************************************************************/
 10 
 11 #ifndef VL_XML
 12 #define VL_XML
 13 
 14 #include "..\Data\Data\VL_Data_String.h"
 15 #include "..\Data\Data\VL_Data_List.h"
 16 #include "..\Data\VL_Stream.h"
 17 #include "..\Data\VL_Uniop.h"
 18 
 19 
 20 namespace vl
 21 {
 22     namespace xml
 23     {
 24         using namespace collection;
 25         using namespace stream;
 26         using namespace uniop;
 27 
 28         enum VLE_XMLNodeType
 29         {
 30             vxntInstruction,
 31             vxntDTD,
 32             vxntElement,
 33             vxntComment,
 34             vxntText,
 35             vxntCData,
 36             vxntAttribute,
 37             vxntDocument
 38         };
 39 
 40         class VL_XMLInstruction;
 41         class VL_XMLDTD;
 42         class VL_XMLElement;
 43         class VL_XMLComment;
 44         class VL_XMLText;
 45         class VL_XMLCData;
 46         class VL_XMLAttribute;
 47         class VL_XMLDocument;
 48 
 49         class VL_XMLError : public VL_Base
 50         {
 51         public:
 52             VUnicodeString                Message;
 53             VInt                        Start;
 54             enum CodeType
 55             {
 56                 UnavailableVersion,
 57                 UnavailableIndex,
 58                 UnavailableName,
 59                 DuplicatedName,
 60                 UnavailableText,
 61                 FileDestroyed,
 62                 FileMistake
 63             }                            Code;
 64 
 65             VL_XMLError(VUnicodeString aMessage , CodeType aCode);
 66             VL_XMLError(VUnicodeString aMessage , CodeType aCode , VInt aStart);
 67         };
 68 
 69         class VL_XMLNode : public VL_Base
 70         {
 71         protected:
 72             VL_XMLNode*                    FParent;
 73             VL_XMLDocument*                FDocument;
 74 
 75             VL_XMLNode(VL_XMLNode* Parent);
 76         public:
 77             ~VL_XMLNode();
 78 
 79             virtual VLE_XMLNodeType        GetType()=0;
 80             virtual void                GetXML(VL_UniBuilder& XML)=0;
 81             VUnicodeString                GetXMLText();
 82         };
 83 
 84         class VL_XMLNodePtr : public VL_Base
 85         {
 86         public:
 87             typedef VL_List<VL_XMLNodePtr , false>        List;
 88         protected:
 89             VL_AutoPtr<VL_XMLNode>        FNode;
 90         public:
 91             VL_XMLNodePtr();
 92             VL_XMLNodePtr(VL_XMLNode* Node);
 93             VL_XMLNodePtr(const VL_XMLNodePtr& Ptr);
 94             ~VL_XMLNodePtr();
 95 
 96             VL_XMLInstruction*            GetInstruction();
 97             VL_XMLDTD*                    GetDTD();
 98             VL_XMLElement*                GetElement();
 99             VL_XMLComment*                GetComment();
100             VL_XMLText*                    GetText();
101             VL_XMLCData*                GetCData();
102             VL_XMLAttribute*            GetAttribute();
103             VL_XMLNode*                    operator->();
104         };
105 
106         class VL_XMLDecoder;
107         class VL_XMLDocument : public VL_XMLNode
108         {
109         protected:
110             VUnicodeString                FVersion;
111             VUnicodeString                FEncoding;
112             VBool                        FStandAlone;
113             VBool                        FUseDeclaration;
114             VL_XMLNodePtr::List            FPrologs;
115             VL_XMLNodePtr::List            FTails;
116             VL_XMLNodePtr                FRootElement;
117             VL_XMLDecoder*                FDecoder;
118 
119             void                        InternalLoad(VUnicodeString String);
120         public:
121             VL_XMLDocument();
122             ~VL_XMLDocument();
123 
124             VLE_XMLNodeType                GetType();
125             void                        GetXML(VL_UniBuilder& XML);
126             VUnicodeString                GetHeadXMLText();
127             VUnicodeString                GetBodyXMLText();
128 
129             void                        Save(IVL_OutputStream* Stream , VBool WriteBOM);
130             void                        Save(VUnicodeString& String);
131             void                        Load(IVL_InputStream* Stream , VLE_CharEncode Encode=vceBOM);    /*Error:FileMistake*/
132             void                        Load(VUnicodeString String);                                    /*Error:FileMistake*/
133             void                        Clear();
134 
135             VUnicodeString                GetVersion();
136             void                        SetVersion(VUnicodeString Version);                                /*Error:UnavailableVersion*/
137             VUnicodeString                GetEncoding();
138             void                        SetEncoding(VUnicodeString Encoding);
139             VBool                        GetStandAlone();
140             void                        SetStandAlone(VBool Use);
141             VBool                        GetUseDeclaration();
142             void                        SetUseDeclaration(VBool Use);
143 
144             VInt                        GetPrologCount();
145             VL_XMLNodePtr                GetProlog(VInt Index);                                            /*Error:UnavailableIndex*/
146             VL_XMLNodePtr                CreatePrologInstruction(VUnicodeString Name , VInt Index=-1);    /*Error:UnavailableName,UnavailableIndex*/
147             VL_XMLNodePtr                CreatePrologDTD(VInt Index=-1);                                    /*Error:UnavailableIndex*/
148             VL_XMLNodePtr                CreatePrologComment(VUnicodeString Value , VInt Index=-1);        /*Error:UnavailableText,UnavailableIndex*/
149             void                        DeleteProlog(VInt Index);                                        /*Error:UnavailableIndex*/
150 
151             VInt                        GetTailCount();
152             VL_XMLNodePtr                GetTail(VInt Index);                                            /*Error:UnavailableIndex*/
153             VL_XMLNodePtr                CreateTailComment(VUnicodeString Value , VInt Index=-1);        /*Error:UnavailableText,UnavailableIndex*/
154             void                        DeleteTail(VInt Index);                                            /*Error:UnavailableIndex*/
155 
156             VL_XMLNodePtr                GetRootElement();
157             VBool                        IsValidatedName(VUnicodeString Name);
158         };
159 
160         class VL_XMLTag : public VL_XMLNode
161         {
162         protected:
163             VUnicodeString                FName;
164             VL_XMLNodePtr::List            FAttributes;
165 
166             VInt                        IndexOfAttribute(VUnicodeString Name);
167             void                        GetNodeHeadXML(VL_UniBuilder& XML);
168 
169             VL_XMLTag(VL_XMLNode* Parent);
170         public:
171             ~VL_XMLTag();
172 
173             VUnicodeString                GetName();
174             void                        SetName(VUnicodeString Name);                                    /*Error:UnavailableName*/
175             VUnicodeString                GetNamespace();
176             VUnicodeString                GetLocal();
177 
178             VL_XMLNodePtr                CreateAttribute(VUnicodeString Name , VUnicodeString Value);    /*Error:UnavailableName,DuplicatedName,UnavailableText*/
179             VBool                        ContainsAttribute(VUnicodeString Name);
180             void                        DeleteAttribute(VUnicodeString Name);                            /*Error:UnavailableName*/
181             VInt                        GetAttributeCount();
182             VL_XMLNodePtr                GetAttribute(VUnicodeString Name);                                /*Error:UnavailableName*/
183             VL_XMLNodePtr                GetAttribute(VInt Index);                                        /*Error:UnavailableIndex*/
184         };
185 
186         class VL_XMLInstruction : public VL_XMLTag
187         {
188             friend class VL_XMLDocument;
189             friend class VL_XMLElement;
190         protected:
191             VL_XMLInstruction(VL_XMLNode* Parent);
192         public:
193             ~VL_XMLInstruction();
194 
195             VLE_XMLNodeType                GetType();
196             void                        GetXML(VL_UniBuilder& XML);
197         };
198 
199         class VL_XMLElement : public VL_XMLTag
200         {
201             friend class VL_XMLDocument;
202         protected:
203             VL_XMLNodePtr::List            FChildren;
204 
205             VL_XMLElement(VL_XMLNode* Parent);
206         public:
207             ~VL_XMLElement();
208 
209             VLE_XMLNodeType                GetType();
210             void                        GetXML(VL_UniBuilder& XML);
211 
212             VL_XMLNodePtr                CreateInstruction(VUnicodeString Name , VInt Index=-1);            /*Error:UnavailableName,UnavailableIndex*/
213             VL_XMLNodePtr                CreateElement(VUnicodeString Name , VInt Index=-1);                /*Error:UnavailableName,UnavailableIndex*/
214             VL_XMLNodePtr                CreateComment(VUnicodeString Text , VInt Index=-1);                /*Error:UnavailableText,UnavailableIndex*/
215             VL_XMLNodePtr                CreateText(VUnicodeString Text , VInt Index=-1);                /*Error:UnavailableText,UnavailableIndex*/
216             VL_XMLNodePtr                CreateCData(VUnicodeString Text , VInt Index=-1);                /*Error:UnavailableText,UnavailableIndex*/
217             VL_XMLNodePtr::List&        GetChildren();
218         };
219 
220         class VL_XMLComment : public VL_XMLNode
221         {
222             friend class VL_XMLDocument;
223             friend class VL_XMLElement;
224         protected:
225             VUnicodeString                FText;
226 
227             VL_XMLComment(VL_XMLNode* Parent);
228         public:
229             ~VL_XMLComment();
230 
231             VLE_XMLNodeType                GetType();
232             void                        GetXML(VL_UniBuilder& XML);
233 
234             VUnicodeString                GetText();
235             void                        SetText(VUnicodeString Text);                                    /*Error:UnavailableText*/
236         };
237 
238         class VL_XMLText : public VL_XMLNode
239         {
240             friend class VL_XMLElement;
241         protected:
242             VUnicodeString                FText;
243 
244             VL_XMLText(VL_XMLNode* Parent);
245         public:
246             ~VL_XMLText();
247 
248             VLE_XMLNodeType                GetType();
249             void                        GetXML(VL_UniBuilder& XML);
250 
251             VUnicodeString                GetText();
252             void                        SetText(VUnicodeString Text);                                    /*Error:UnavailableText*/
253         };
254 
255         class VL_XMLCData : public VL_XMLNode
256         {
257             friend class VL_XMLElement;
258         protected:
259             VUnicodeString                FText;
260 
261             VL_XMLCData(VL_XMLNode* Parent);
262         public:
263             ~VL_XMLCData();
264 
265             VLE_XMLNodeType                GetType();
266             void                        GetXML(VL_UniBuilder& XML);
267 
268             VUnicodeString                GetText();
269             void                        SetText(VUnicodeString Text);                                    /*Error:UnavailableText*/
270         };
271 
272         class VL_XMLAttribute : public VL_XMLNode
273         {
274             friend class VL_XMLTag;
275         protected:
276             VUnicodeString                FName;
277             VUnicodeString                FText;
278             VBool                        FQuot;
279 
280             VL_XMLAttribute(VL_XMLNode* Parent);
281         public:
282             ~VL_XMLAttribute();
283 
284             VLE_XMLNodeType                GetType();
285             void                        GetXML(VL_UniBuilder& XML);
286 
287             VUnicodeString                GetName();
288             VUnicodeString                GetNamespace();
289             VUnicodeString                GetLocal();
290             VUnicodeString                GetText();
291             void                        SetText(VUnicodeString Text);                                    /*Error:UnavailableText*/
292         };
293     }
294 }
295 
296 #endif

    使用自己做的正则表达式构造的一系列XML分析工具:
  1 /*********************************************************************************************************
  2 VL_XMLDecoder
  3 *********************************************************************************************************/
  4 
  5     struct VLS_XMLString
  6     {
  7         PWChar                    Start;
  8         VInt                    Length;
  9 
 10         VLS_XMLString()
 11         {
 12             Start=0;
 13             Length=0;
 14         }
 15 
 16         VLS_XMLString(PWChar aStart , VInt aLength)
 17         {
 18             Start=aStart;
 19             Length=aLength;
 20         }
 21 
 22         VBool Is(PCWChar String)
 23         {
 24             PCWChar Buffer=Start;
 25             while(*String)
 26             {
 27                 if(*Buffer++!=*String++)
 28                 {
 29                     return false;
 30                 }
 31             }
 32             return true;
 33         }
 34 
 35         VUnicodeString ToString()
 36         {
 37             return VUnicodeString(Start,Length);
 38         }
 39     };
 40 
 41     struct VLS_XMLAttribute
 42     {
 43         typedef VL_List<VLS_XMLAttribute , true>    List;
 44 
 45         VLS_XMLString            Name;
 46         VLS_XMLString            Value;
 47     };
 48 
 49     struct VLS_XMLElement
 50     {
 51         VLS_XMLAttribute::List    Attributes;
 52         VLS_XMLString            Name;
 53         VWChar                    StartChar;
 54         VWChar                    EndChar;
 55     };
 56 
 57     class VL_XMLDecoder : public VL_Base
 58     {
 59     public:
 60         VL_RegMatch Reg_CData;
 61         VL_RegMatch Reg_Text;
 62         VL_RegMatch Reg_Comment;
 63         VL_RegMatch Reg_Name;
 64         VL_RegMatch Reg_Value;
 65 
 66         VL_XMLDecoder():
 67             Reg_CData(L"\\<!\\[CDATA\\[([^\\]]|\\][^\\]]|\\]\\][^\\>])*\\]\\]\\>"),
 68             Reg_Text(L"[^\\<\\>]+"),
 69             Reg_Comment(L"\\<!\\-\\-([^\\-]|\\-[^\\-]|\\-\\-[^\\>])*\\-\\-\\>"),
 70             Reg_Name(L"[a-zA-Z_][a-zA-Z0-9\\-_.:]*"),
 71             Reg_Value(L"\"[^\"]*\"")
 72         {
 73         }
 74 
 75         void PassWhite(VLS_XMLString& String)
 76         {
 77             while(String.Length)
 78             {
 79                 switch(*String.Start)
 80                 {
 81                 case L' ':case L'\t':case L'\r':case L'\n':
 82                     String.Start++;
 83                     String.Length--;
 84                     break;
 85                 default:
 86                     return;
 87                 }
 88             }
 89         }
 90 
 91         VLS_XMLString GetCData(VLS_XMLString& Input)
 92         {
 93             VInt Length=Reg_CData.MatchBuffer(Input.Start);
 94             if(Length==-1)
 95             {
 96                 return VLS_XMLString();
 97             }
 98             else
 99             {
100                 VLS_XMLString Result(Input.Start+9,Length-12);
101                 Input.Start+=Length;
102                 Input.Length-=Length;
103                 return Result;
104             }
105         }
106 
107         VLS_XMLString GetText(VLS_XMLString& Input)
108         {
109             VInt Length=Reg_Text.MatchBuffer(Input.Start);
110             if(Length==-1)
111             {
112                 return VLS_XMLString();
113             }
114             else
115             {
116                 VLS_XMLString Result(Input.Start,Length);
117                 Input.Start+=Length;
118                 Input.Length-=Length;
119                 return Result;
120             }
121         }
122 
123         VLS_XMLString GetComment(VLS_XMLString& Input , VBool PassWhiteCharacters=false)
124         {
125             if(PassWhiteCharacters)PassWhite(Input);
126             VInt Length=Reg_Comment.MatchBuffer(Input.Start);
127             if(Length==-1)
128             {
129                 return VLS_XMLString();
130             }
131             else
132             {
133                 VLS_XMLString Result(Input.Start+4,Length-7);
134                 Input.Start+=Length;
135                 Input.Length-=Length;
136                 return Result;
137             }
138         }
139 
140         VLS_XMLString GetName(VLS_XMLString& Input , VBool PassWhiteCharacters)
141         {
142             if(PassWhiteCharacters)PassWhite(Input);
143             VInt Length=Reg_Name.MatchBuffer(Input.Start);
144             if(Length==-1)
145             {
146                 return VLS_XMLString();
147             }
148             else
149             {
150                 VLS_XMLString Result(Input.Start,Length);
151                 Input.Start+=Length;
152                 Input.Length-=Length;
153                 return Result;
154             }
155         }
156 
157         VLS_XMLString GetValue(VLS_XMLString& Input , VBool PassWhiteCharacters)
158         {
159             if(PassWhiteCharacters)PassWhite(Input);
160             VInt Length=Reg_Value.MatchBuffer(Input.Start);
161             if(Length==-1)
162             {
163                 return VLS_XMLString();
164             }
165             else
166             {
167                 VLS_XMLString Result(Input.Start+1,Length-2);
168                 Input.Start+=Length;
169                 Input.Length-=Length;
170                 return Result;
171             }
172         }
173 
174         VBool Test(VLS_XMLString& Input , PCWChar String , VBool PassWhiteCharacters)
175         {
176             if(PassWhiteCharacters)PassWhite(Input);
177             PWChar Buffer=Input.Start;
178             while(*String)
179             {
180                 if(*Buffer++!=*String++)
181                 {
182                     return false;
183                 }
184             }
185             Input.Length-=Buffer-Input.Start;
186             Input.Start=Buffer;
187             return true;
188         }
189 
190         PCWChar GetElement(VLS_XMLString& Input , VLS_XMLElement& Element , VBool CompleteAttribute , VBool PassWhiteCharacters)
191         {
192             if(PassWhiteCharacters)PassWhite(Input);
193             if(Test(Input,L"<?",false))
194             {
195                 Element.StartChar=L'?';
196             }
197             else if(Test(Input,L"<!",false))
198             {
199                 Element.StartChar=L'!';
200             }
201             else if(Test(Input,L"</",false))
202             {
203                 Element.StartChar=L'/';
204             }
205             else if(Test(Input,L"<",false))
206             {
207                 Element.StartChar=0;
208             }
209             else
210             {
211                 return L"错误的Element开始字符。";
212             }
213             Element.Name=GetName(Input,true);
214             if(!Element.Name.Start)
215             {
216                 return L"错误的Element名称。";
217             }
218             Element.Attributes.Clear();
219             while(true)
220             {
221                 PassWhite(Input);
222                 if(Test(Input,L"?>",false))
223                 {
224                     Element.EndChar=L'?';
225                     break;
226                 }
227                 else if(Test(Input,L"/>",false))
228                 {
229                     Element.EndChar=L'/';
230                     break;
231                 }
232                 else if(Test(Input,L">",false))
233                 {
234                     Element.EndChar=0;
235                     break;
236                 }
237                 else
238                 {
239                     VLS_XMLAttribute Attribute;
240                     Attribute.Name=GetName(Input,false);
241                     if(Attribute.Name.Start)
242                     {
243                         if(Test(Input,L"=",true))
244                         {
245                             Attribute.Value=GetValue(Input,true);
246                             if(!Attribute.Value.Start)
247                             {
248                                 return L"错误的Attribute值。";
249                             }
250                         }
251                     }
252                     else
253                     {
254                         Attribute.Value=GetValue(Input,true);
255                     }
256                     if(CompleteAttribute)
257                     {
258                         if(!Attribute.Name.Start)
259                         {
260                             return L"缺少Attribute名称。";
261                         }
262                         else if(!Attribute.Value.Start)
263                         {
264                             return L"缺少Attribute值。";
265                         }
266                     }
267                     Element.Attributes.Add(Attribute);
268                 }
269             }
270             return 0;
271         }
272     };

    分析部分,其中使用了一个自己做的贪婪正则表达式分析器分析XML的编码部分:
  1 /*********************************************************************************************************
  2 VL_XMLDocument
  3 *********************************************************************************************************/
  4 
  5     void VL_XMLDocument::InternalLoad(VUnicodeString String)
  6     {
  7         if(!FDecoder)
  8         {
  9             FDecoder=new VL_XMLDecoder;
 10         }
 11         VLS_XMLString Input(String.Buffer(),String.Length());
 12         {
 13             /*检查第一个标记是否<?xml?>*/
 14             FUseDeclaration=false;
 15             VLS_XMLString Head=Input;
 16             VLS_XMLElement Element;
 17             PCWChar ErrorMessage=FDecoder->GetElement(Head,Element,true,false);
 18             if(!ErrorMessage)
 19             {
 20                 if(Element.Name.Is(L"xml"))
 21                 {
 22                     /*获取<?xml?>标记的三个属性*/
 23                     FUseDeclaration=true;
 24                     if(Element.Attributes.GetCount()>=1)
 25                     {
 26                         if(Element.Attributes[0].Name.Is(L"version"))
 27                         {
 28                             if(Element.Attributes[0].Value.Is(L"1.0"))
 29                             {
 30                                 FVersion=L"1.0";
 31                             }
 32                             else
 33                             {
 34                                 throw VL_XMLError(L"错误的版本号,分析器只支持1.0版本的XML文件。",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 35                             }
 36                         }
 37                         else
 38                         {
 39                             throw VL_XMLError(L"?xml标记的第一个属性必须是version。",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 40                         }
 41                     }
 42                     if(Element.Attributes.GetCount()>=2)
 43                     {
 44                         if(Element.Attributes[1].Name.Is(L"encoding"))
 45                         {
 46                             FEncoding=Element.Attributes[1].Value.ToString();
 47                         }
 48                         else
 49                         {
 50                             throw VL_XMLError(L"?xml标记的第二个属性必须是encoding。",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 51                         }
 52                     }
 53                     if(Element.Attributes.GetCount()>=3)
 54                     {
 55                         if(Element.Attributes[2].Name.Is(L"standalone"))
 56                         {
 57                             if(Element.Attributes[2].Value.Is(L"yes"))
 58                             {
 59                                 FStandAlone=true;
 60                             }
 61                             else if(Element.Attributes[2].Value.Is(L"no"))
 62                             {
 63                                 FStandAlone=false;
 64                             }
 65                             else
 66                             {
 67                                 throw VL_XMLError(L"?xml的standalone的属性只能取\"yes\"或\"no\"",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 68                             }
 69                         }
 70                         else
 71                         {
 72                             throw VL_XMLError(L"?xml标记的第三个属性必须是encoding。",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 73                         }
 74                     }
 75                     if(Element.Attributes.GetCount()>=4)
 76                     {
 77                         throw VL_XMLError(L"?xml标记只能有version、encoding和standalone属性。",VL_XMLError::FileMistake,Head.Start-String.Buffer());
 78                     }
 79                     Input=Head;
 80                 }
 81             }
 82             else
 83             {
 84                 throw VL_XMLError(ErrorMessage,VL_XMLError::FileMistake,Input.Start-String.Buffer());
 85             }
 86         }
 87         /*获取Prolog*/
 88         VLS_XMLElement Element;
 89         while(true)
 90         {
 91             /*尝试分析Comment*/
 92             VLS_XMLString Comment=FDecoder->GetComment(Input,true);
 93             if(Comment.Start)
 94             {
 95                 CreatePrologComment(Comment.ToString());
 96             }
 97             else
 98             {
 99                 /*分析Processing Instruction*/
100                 PCWChar ErrorMessage=FDecoder->GetElement(Input,Element,true,true);
101                 if(ErrorMessage)
102                 {
103                     throw VL_XMLError(ErrorMessage,VL_XMLError::FileMistake,Input.Start-String.Buffer());
104                 }
105                 else if(Element.StartChar==L'?')
106                 {
107                     if(Element.EndChar!=L'?')
108                     {
109                         throw VL_XMLError(VUnicodeString(L"Processing Instruction标记必须使用?>结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
110                     }
111                     try
112                     {
113                         VL_XMLInstruction* Instruction=CreatePrologInstruction(Element.Name.ToString()).GetInstruction();
114                         for(VInt i=0;i<Element.Attributes.GetCount();i++)
115                         {
116                             Instruction->CreateAttribute(Element.Attributes[i].Name.ToString(),Element.Attributes[i].Value.ToString());
117                         }
118                     }
119                     catch(VL_XMLError& e)
120                     {
121                         e.Start=Input.Start-String.Buffer();
122                         throw e;
123                     }
124                 }
125                 else if(Element.StartChar==0)
126                 {
127                     break;
128                 }
129                 else
130                 {
131                     throw VL_XMLError(VUnicodeString(L"遇到不明标记类型:<。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
132                 }
133             }
134         }
135         /*填充RootElement信息*/
136         VL_List<VL_XMLElement* , true> ElementStack;
137         VL_XMLElement* Last=FRootElement.GetElement();
138         ElementStack.Add(Last);
139         try
140         {
141             FRootElement.GetElement()->SetName(Element.Name.ToString());
142             for(VInt i=0;i<Element.Attributes.GetCount();i++)
143             {
144                 Last->CreateAttribute(Element.Attributes[i].Name.ToString(),Element.Attributes[i].Value.ToString());
145             }
146             switch(Element.EndChar)
147             {
148             case L'/':
149                 ElementStack.Fetch();
150                 Last=0;
151                 break;
152             case 0:
153                 break;
154             default:
155                 throw VL_XMLError(VUnicodeString(L"Element标记必须使用/>或>结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
156             }
157         }
158         catch(VL_XMLError& e)
159         {
160             e.Start=Input.Start-String.Buffer();
161             throw e;
162         }
163         /*填充RootElement内容*/
164         while(Last)
165         {
166             VLS_XMLString XMLString=FDecoder->GetComment(Input);
167             if(XMLString.Start)
168             {
169                 Last->CreateComment(XMLString.ToString());
170             }
171             else if((XMLString=FDecoder->GetCData(Input)).Start)
172             {
173                 Last->CreateCData(XMLString.ToString());
174             }
175             else if((XMLString=FDecoder->GetText(Input)).Start)
176             {
177                 Last->CreateText(XMLString.ToString());
178             }
179             else
180             {
181                 PCWChar ErrorMessage=FDecoder->GetElement(Input,Element,true,false);
182                 if(ErrorMessage)
183                 {
184                     throw VL_XMLError(ErrorMessage,VL_XMLError::FileMistake,Input.Start-String.Buffer());
185                 }
186                 else if(Element.StartChar==L'?')
187                 {
188                     if(Element.EndChar!=L'?')
189                     {
190                         throw VL_XMLError(VUnicodeString(L"Processing Instruction标记必须使用?>结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
191                     }
192                     try
193                     {
194                         VL_XMLInstruction* Instruction=Last->CreateInstruction(Element.Name.ToString()).GetInstruction();
195                         for(VInt i=0;i<Element.Attributes.GetCount();i++)
196                         {
197                             Instruction->CreateAttribute(Element.Attributes[i].Name.ToString(),Element.Attributes[i].Value.ToString());
198                         }
199                     }
200                     catch(VL_XMLError& e)
201                     {
202                         e.Start=Input.Start-String.Buffer();
203                         throw e;
204                     }
205                 }
206                 else if(Element.StartChar==0)
207                 {
208                     try
209                     {
210                         VL_XMLElement* Current=Last->CreateElement(Element.Name.ToString()).GetElement();
211                         if(Element.EndChar==L'/')
212                         {
213                         }
214                         else if(Element.EndChar==0)
215                         {
216                             ElementStack.Add(Last=Current);
217                         }
218                         else
219                         {
220                             throw VL_XMLError(VUnicodeString(L"Element标记必须使用/>或>结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
221                         }
222                         for(VInt i=0;i<Element.Attributes.GetCount();i++)
223                         {
224                             Current->CreateAttribute(Element.Attributes[i].Name.ToString(),Element.Attributes[i].Value.ToString());
225                         }
226                     }
227                     catch(VL_XMLError& e)
228                     {
229                         e.Start=Input.Start-String.Buffer();
230                         throw e;
231                     }
232                 }
233                 else if(Element.StartChar==L'/')
234                 {
235                     if(Element.Name.ToString()!=Last->GetName())
236                     {
237                         throw VL_XMLError(VUnicodeString(L"不匹配的Element结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
238                     }
239                     else if(Element.EndChar!=0)
240                     {
241                         throw VL_XMLError(VUnicodeString(L"Element结束标记必须使用>结束。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
242                     }
243                     else if(Element.Attributes.GetCount()>0)
244                     {
245                         throw VL_XMLError(VUnicodeString(L"Element结束标记不能有Attribute。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
246                     }
247                     else
248                     {
249                         ElementStack.Fetch();
250                         if(ElementStack.GetCount())
251                         {
252                             Last=ElementStack[ElementStack.GetCount()-1];
253                         }
254                         else
255                         {
256                             Last=0;
257                         }
258                     }
259                 }
260                 else
261                 {
262                     throw VL_XMLError(VUnicodeString(L"遇到不明标记类型:<。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
263                 }
264             }
265         }
266         /*获取Tail*/
267         while(true)
268         {
269             VLS_XMLString XMLString=FDecoder->GetComment(Input,true);
270             if(XMLString.Start)
271             {
272                 CreateTailComment(XMLString.ToString());
273             }
274             else
275             {
276                 break;
277             }
278         }
279         if(Input.Length)
280         {
281             throw VL_XMLError(VUnicodeString(L"XML文件末尾出现多余字符。")+Element.StartChar,VL_XMLError::FileMistake,Input.Start-String.Buffer());
282         }
283     }
284 
285     void VL_XMLDocument::Load(IVL_InputStream* Stream , VLE_CharEncode Encode)
286     {
287         VUnicodeString String;
288         VL_TextInput Input(Stream,false,Encode);
289         if(Input.GetEncode()==vceMbcs)
290         {
291             VUnicodeString Head;
292             VLE_CharEncode NewEncode=vceMbcs;
293             VInt Position=Stream->Position();
294             VChar Current=0;
295             VBool NoEncoding=true;
296             /*读取到">"结束的字符串*/
297             while(Stream->Read(&Current,sizeof(Current)))
298             {
299                 if(Current=='>')
300                 {
301                     break;
302                 }
303             }
304             /*如果读取成功则进行encoding判断*/
305             if(Current=='>')
306             {
307                 /*获取<?xml?>标记*/
308                 VInt Count=Stream->Position()-Position;
309                 Stream->MoveTo(Position);
310                 Input.Read(Head,Count);
311                 VL_RegExp Declaration(L"\\s*\\<\\?\\s*xml(\\s+(?:<#attribute>[a-zA-Z_][a-zA-Z0-9\\-_.]*)\\s*=\\s*\"(?:<#value>[^\"]*)\")*\\s*\\?\\>",true);
312                 VL_RegExp::ResultPtr Result=Declaration.MatchWhole(Head);
313                 /*如果获取成功则获取encoding属性*/
314                 if(Result->IsMatched())
315                 {
316                     if(Result->HasStorage(L"attribute"))
317                     {
318                         Count=Result->GetStorageCount(L"attribute");
319                         for(VInt i=0;i<Count;i++)
320                         {
321                             if(Result->GetStorage(L"attribute",i)==L"encoding")
322                             {
323                                 /*encoding存在,获取编码*/
324                                 VUnicodeString Encoding=Result->GetStorage(L"value",i).LowerCase();
325                                 if(Encoding==L"utf-8")
326                                 {
327                                     NewEncode=vceUtf8;
328                                     NoEncoding=false;
329                                 }
330                                 else if(Encoding==L"utf-16")
331                                 {
332                                     NewEncode=vceUtf16;
333                                     NoEncoding=false;
334                                 }
335                                 break;
336                             }
337                         }
338                     }
339                 }
340             }
341             /*根据不同的Encoding状况组装完整的XML字符串*/
342             if(NoEncoding)
343             {
344                 Stream->MoveTo(Position);
345                 Input.Read(String);
346             }
347             else
348             {
349                 VL_TextInput Input2(Stream,false,NewEncode);
350                 Input2.Read(String);
351                 String.Insert(0,Head);
352             }
353         }
354         else
355         {
356             Input.Read(String);
357         }
358         Load(String);
359     }
360 
361     void VL_XMLDocument::Load(VUnicodeString String)
362     {
363         VUnicodeString aVersion=FVersion;
364         VUnicodeString aEncoding=FEncoding;
365         VBool aStandAlone=FStandAlone;
366         VBool aUseDeclaration=FUseDeclaration;
367         VL_XMLNodePtr aRootElement=FRootElement;
368         VL_XMLNodePtr::List aPrologs=FPrologs;
369         VL_XMLNodePtr::List aTails=FTails;
370         try
371         {
372             Clear();
373             InternalLoad(String);
374         }
375         catch(VL_XMLError& e)
376         {
377             FVersion=aVersion;
378             FEncoding=aEncoding;
379             FStandAlone=aStandAlone;
380             FUseDeclaration=aUseDeclaration;
381             FRootElement=aRootElement;
382             FPrologs=aPrologs;
383             FTails=aTails;
384             throw e;
385         }
386     }
posted on 2008-06-19 05:28 陈梓瀚(vczh) 阅读(3150) 评论(8)  编辑 收藏 引用 所属分类: C++

评论:
# re: 做了一个XML解释器 2008-06-19 07:45 | soulfvi
.................................
说什么好呢  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-19 16:22 | toperray
很好,小伙子,坚持下去,呵呵。  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-19 17:12 | 浪迹天涯
mark 学习学习  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-19 18:03 | werw
强悍啊~~~~~~~~~  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-19 21:25 | 空明流转
日,你真他妈的有闲工夫。  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-19 21:58 | 陈梓瀚(vczh)
事实证明,复习到囧囧有神的时候最好的缓解办法就是信手拈一个程序了……  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-20 01:23 | rwei
太有才了  回复  更多评论
  
# re: 做了一个XML解释器 2008-06-26 05:46 | Vampire.Kiss
其实仔细看MSDN的话。
你会发现有H内容  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理