为了纪念自己为了明天的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++