corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) 2006-2014, openmetaverse.org |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * - Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * |
||
8 | * - Redistributions of source code must retain the above copyright notice, this |
||
9 | * list of conditions and the following disclaimer. |
||
10 | * - Neither the name of the openmetaverse.org nor the names |
||
11 | * of its contributors may be used to endorse or promote products derived from |
||
12 | * this software without specific prior written permission. |
||
13 | * |
||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
24 | * POSSIBILITY OF SUCH DAMAGE. |
||
25 | */ |
||
26 | |||
27 | using System; |
||
28 | using System.Collections.Generic; |
||
29 | using System.IO; |
||
30 | using System.Xml; |
||
31 | using System.Xml.Schema; |
||
32 | using System.Text; |
||
33 | |||
34 | namespace OpenMetaverse.StructuredData |
||
35 | { |
||
36 | /// <summary> |
||
37 | /// |
||
38 | /// </summary> |
||
39 | public static partial class OSDParser |
||
40 | { |
||
41 | private static XmlSchema XmlSchema; |
||
42 | private static XmlTextReader XmlTextReader; |
||
43 | private static string LastXmlErrors = String.Empty; |
||
44 | private static object XmlValidationLock = new object(); |
||
45 | |||
46 | /// <summary> |
||
47 | /// |
||
48 | /// </summary> |
||
49 | /// <param name="xmlData"></param> |
||
50 | /// <returns></returns> |
||
51 | public static OSD DeserializeLLSDXml(byte[] xmlData) |
||
52 | { |
||
53 | return DeserializeLLSDXml(new XmlTextReader(new MemoryStream(xmlData, false))); |
||
54 | } |
||
55 | |||
56 | public static OSD DeserializeLLSDXml(Stream xmlStream) |
||
57 | { |
||
58 | return DeserializeLLSDXml(new XmlTextReader(xmlStream)); |
||
59 | } |
||
60 | |||
61 | /// <summary> |
||
62 | /// |
||
63 | /// </summary> |
||
64 | /// <param name="xmlData"></param> |
||
65 | /// <returns></returns> |
||
66 | public static OSD DeserializeLLSDXml(string xmlData) |
||
67 | { |
||
68 | byte[] bytes = Utils.StringToBytes(xmlData); |
||
69 | return DeserializeLLSDXml(new XmlTextReader(new MemoryStream(bytes, false))); |
||
70 | } |
||
71 | |||
72 | /// <summary> |
||
73 | /// |
||
74 | /// </summary> |
||
75 | /// <param name="xmlData"></param> |
||
76 | /// <returns></returns> |
||
77 | public static OSD DeserializeLLSDXml(XmlTextReader xmlData) |
||
78 | { |
||
79 | try |
||
80 | { |
||
81 | xmlData.Read(); |
||
82 | SkipWhitespace(xmlData); |
||
83 | |||
84 | xmlData.Read(); |
||
85 | OSD ret = ParseLLSDXmlElement(xmlData); |
||
86 | |||
87 | return ret; |
||
88 | } |
||
89 | catch |
||
90 | { |
||
91 | return new OSD(); |
||
92 | } |
||
93 | } |
||
94 | |||
95 | /// <summary> |
||
96 | /// |
||
97 | /// </summary> |
||
98 | /// <param name="data"></param> |
||
99 | /// <returns></returns> |
||
100 | public static byte[] SerializeLLSDXmlBytes(OSD data) |
||
101 | { |
||
102 | return Encoding.UTF8.GetBytes(SerializeLLSDXmlString(data)); |
||
103 | } |
||
104 | |||
105 | /// <summary> |
||
106 | /// |
||
107 | /// </summary> |
||
108 | /// <param name="data"></param> |
||
109 | /// <returns></returns> |
||
110 | public static string SerializeLLSDXmlString(OSD data) |
||
111 | { |
||
112 | StringWriter sw = new StringWriter(); |
||
113 | XmlTextWriter writer = new XmlTextWriter(sw); |
||
114 | writer.Formatting = Formatting.None; |
||
115 | |||
116 | writer.WriteStartElement(String.Empty, "llsd", String.Empty); |
||
117 | SerializeLLSDXmlElement(writer, data); |
||
118 | writer.WriteEndElement(); |
||
119 | |||
120 | writer.Close(); |
||
121 | |||
122 | return sw.ToString(); |
||
123 | } |
||
124 | |||
125 | /// <summary> |
||
126 | /// |
||
127 | /// </summary> |
||
128 | /// <param name="writer"></param> |
||
129 | /// <param name="data"></param> |
||
130 | public static void SerializeLLSDXmlElement(XmlTextWriter writer, OSD data) |
||
131 | { |
||
132 | switch (data.Type) |
||
133 | { |
||
134 | case OSDType.Unknown: |
||
135 | writer.WriteStartElement(String.Empty, "undef", String.Empty); |
||
136 | writer.WriteEndElement(); |
||
137 | break; |
||
138 | case OSDType.Boolean: |
||
139 | writer.WriteStartElement(String.Empty, "boolean", String.Empty); |
||
140 | writer.WriteString(data.AsString()); |
||
141 | writer.WriteEndElement(); |
||
142 | break; |
||
143 | case OSDType.Integer: |
||
144 | writer.WriteStartElement(String.Empty, "integer", String.Empty); |
||
145 | writer.WriteString(data.AsString()); |
||
146 | writer.WriteEndElement(); |
||
147 | break; |
||
148 | case OSDType.Real: |
||
149 | writer.WriteStartElement(String.Empty, "real", String.Empty); |
||
150 | writer.WriteString(data.AsString()); |
||
151 | writer.WriteEndElement(); |
||
152 | break; |
||
153 | case OSDType.String: |
||
154 | writer.WriteStartElement(String.Empty, "string", String.Empty); |
||
155 | writer.WriteString(data.AsString()); |
||
156 | writer.WriteEndElement(); |
||
157 | break; |
||
158 | case OSDType.UUID: |
||
159 | writer.WriteStartElement(String.Empty, "uuid", String.Empty); |
||
160 | writer.WriteString(data.AsString()); |
||
161 | writer.WriteEndElement(); |
||
162 | break; |
||
163 | case OSDType.Date: |
||
164 | writer.WriteStartElement(String.Empty, "date", String.Empty); |
||
165 | writer.WriteString(data.AsString()); |
||
166 | writer.WriteEndElement(); |
||
167 | break; |
||
168 | case OSDType.URI: |
||
169 | writer.WriteStartElement(String.Empty, "uri", String.Empty); |
||
170 | writer.WriteString(data.AsString()); |
||
171 | writer.WriteEndElement(); |
||
172 | break; |
||
173 | case OSDType.Binary: |
||
174 | writer.WriteStartElement(String.Empty, "binary", String.Empty); |
||
175 | writer.WriteStartAttribute(String.Empty, "encoding", String.Empty); |
||
176 | writer.WriteString("base64"); |
||
177 | writer.WriteEndAttribute(); |
||
178 | writer.WriteString(data.AsString()); |
||
179 | writer.WriteEndElement(); |
||
180 | break; |
||
181 | case OSDType.Map: |
||
182 | OSDMap map = (OSDMap)data; |
||
183 | writer.WriteStartElement(String.Empty, "map", String.Empty); |
||
184 | foreach (KeyValuePair<string, OSD> kvp in map) |
||
185 | { |
||
186 | writer.WriteStartElement(String.Empty, "key", String.Empty); |
||
187 | writer.WriteString(kvp.Key); |
||
188 | writer.WriteEndElement(); |
||
189 | |||
190 | SerializeLLSDXmlElement(writer, kvp.Value); |
||
191 | } |
||
192 | writer.WriteEndElement(); |
||
193 | break; |
||
194 | case OSDType.Array: |
||
195 | OSDArray array = (OSDArray)data; |
||
196 | writer.WriteStartElement(String.Empty, "array", String.Empty); |
||
197 | for (int i = 0; i < array.Count; i++) |
||
198 | { |
||
199 | SerializeLLSDXmlElement(writer, array[i]); |
||
200 | } |
||
201 | writer.WriteEndElement(); |
||
202 | break; |
||
203 | } |
||
204 | } |
||
205 | |||
206 | /// <summary> |
||
207 | /// |
||
208 | /// </summary> |
||
209 | /// <param name="xmlData"></param> |
||
210 | /// <param name="error"></param> |
||
211 | /// <returns></returns> |
||
212 | public static bool TryValidateLLSDXml(XmlTextReader xmlData, out string error) |
||
213 | { |
||
214 | lock (XmlValidationLock) |
||
215 | { |
||
216 | LastXmlErrors = String.Empty; |
||
217 | XmlTextReader = xmlData; |
||
218 | |||
219 | CreateLLSDXmlSchema(); |
||
220 | |||
221 | XmlReaderSettings readerSettings = new XmlReaderSettings(); |
||
222 | readerSettings.ValidationType = ValidationType.Schema; |
||
223 | readerSettings.Schemas.Add(XmlSchema); |
||
224 | readerSettings.ValidationEventHandler += new ValidationEventHandler(LLSDXmlSchemaValidationHandler); |
||
225 | |||
226 | XmlReader reader = XmlReader.Create(xmlData, readerSettings); |
||
227 | |||
228 | try |
||
229 | { |
||
230 | while (reader.Read()) { } |
||
231 | } |
||
232 | catch (XmlException) |
||
233 | { |
||
234 | error = LastXmlErrors; |
||
235 | return false; |
||
236 | } |
||
237 | |||
238 | if (LastXmlErrors == String.Empty) |
||
239 | { |
||
240 | error = null; |
||
241 | return true; |
||
242 | } |
||
243 | else |
||
244 | { |
||
245 | error = LastXmlErrors; |
||
246 | return false; |
||
247 | } |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /// <summary> |
||
252 | /// |
||
253 | /// </summary> |
||
254 | /// <param name="reader"></param> |
||
255 | /// <returns></returns> |
||
256 | private static OSD ParseLLSDXmlElement(XmlTextReader reader) |
||
257 | { |
||
258 | SkipWhitespace(reader); |
||
259 | |||
260 | if (reader.NodeType != XmlNodeType.Element) |
||
261 | throw new OSDException("Expected an element"); |
||
262 | |||
263 | string type = reader.LocalName; |
||
264 | OSD ret; |
||
265 | |||
266 | switch (type) |
||
267 | { |
||
268 | case "undef": |
||
269 | if (reader.IsEmptyElement) |
||
270 | { |
||
271 | reader.Read(); |
||
272 | return new OSD(); |
||
273 | } |
||
274 | |||
275 | reader.Read(); |
||
276 | SkipWhitespace(reader); |
||
277 | ret = new OSD(); |
||
278 | break; |
||
279 | case "boolean": |
||
280 | if (reader.IsEmptyElement) |
||
281 | { |
||
282 | reader.Read(); |
||
283 | return OSD.FromBoolean(false); |
||
284 | } |
||
285 | |||
286 | if (reader.Read()) |
||
287 | { |
||
288 | string s = reader.ReadString().Trim(); |
||
289 | |||
290 | if (!String.IsNullOrEmpty(s) && (s == "true" || s == "1")) |
||
291 | { |
||
292 | ret = OSD.FromBoolean(true); |
||
293 | break; |
||
294 | } |
||
295 | } |
||
296 | |||
297 | ret = OSD.FromBoolean(false); |
||
298 | break; |
||
299 | case "integer": |
||
300 | if (reader.IsEmptyElement) |
||
301 | { |
||
302 | reader.Read(); |
||
303 | return OSD.FromInteger(0); |
||
304 | } |
||
305 | |||
306 | if (reader.Read()) |
||
307 | { |
||
308 | int value = 0; |
||
309 | Int32.TryParse(reader.ReadString().Trim(), out value); |
||
310 | ret = OSD.FromInteger(value); |
||
311 | break; |
||
312 | } |
||
313 | |||
314 | ret = OSD.FromInteger(0); |
||
315 | break; |
||
316 | case "real": |
||
317 | if (reader.IsEmptyElement) |
||
318 | { |
||
319 | reader.Read(); |
||
320 | return OSD.FromReal(0d); |
||
321 | } |
||
322 | |||
323 | if (reader.Read()) |
||
324 | { |
||
325 | double value = 0d; |
||
326 | string str = reader.ReadString().Trim().ToLower(); |
||
327 | |||
328 | if (str == "nan") |
||
329 | value = Double.NaN; |
||
330 | else |
||
331 | Utils.TryParseDouble(str, out value); |
||
332 | |||
333 | ret = OSD.FromReal(value); |
||
334 | break; |
||
335 | } |
||
336 | |||
337 | ret = OSD.FromReal(0d); |
||
338 | break; |
||
339 | case "uuid": |
||
340 | if (reader.IsEmptyElement) |
||
341 | { |
||
342 | reader.Read(); |
||
343 | return OSD.FromUUID(UUID.Zero); |
||
344 | } |
||
345 | |||
346 | if (reader.Read()) |
||
347 | { |
||
348 | UUID value = UUID.Zero; |
||
349 | UUID.TryParse(reader.ReadString().Trim(), out value); |
||
350 | ret = OSD.FromUUID(value); |
||
351 | break; |
||
352 | } |
||
353 | |||
354 | ret = OSD.FromUUID(UUID.Zero); |
||
355 | break; |
||
356 | case "date": |
||
357 | if (reader.IsEmptyElement) |
||
358 | { |
||
359 | reader.Read(); |
||
360 | return OSD.FromDate(Utils.Epoch); |
||
361 | } |
||
362 | |||
363 | if (reader.Read()) |
||
364 | { |
||
365 | DateTime value = Utils.Epoch; |
||
366 | DateTime.TryParse(reader.ReadString().Trim(), out value); |
||
367 | ret = OSD.FromDate(value); |
||
368 | break; |
||
369 | } |
||
370 | |||
371 | ret = OSD.FromDate(Utils.Epoch); |
||
372 | break; |
||
373 | case "string": |
||
374 | if (reader.IsEmptyElement) |
||
375 | { |
||
376 | reader.Read(); |
||
377 | return OSD.FromString(String.Empty); |
||
378 | } |
||
379 | |||
380 | if (reader.Read()) |
||
381 | { |
||
382 | ret = OSD.FromString(reader.ReadString()); |
||
383 | break; |
||
384 | } |
||
385 | |||
386 | ret = OSD.FromString(String.Empty); |
||
387 | break; |
||
388 | case "binary": |
||
389 | if (reader.IsEmptyElement) |
||
390 | { |
||
391 | reader.Read(); |
||
392 | return OSD.FromBinary(Utils.EmptyBytes); |
||
393 | } |
||
394 | |||
395 | if (reader.GetAttribute("encoding") != null && reader.GetAttribute("encoding") != "base64") |
||
396 | throw new OSDException("Unsupported binary encoding: " + reader.GetAttribute("encoding")); |
||
397 | |||
398 | if (reader.Read()) |
||
399 | { |
||
400 | try |
||
401 | { |
||
402 | ret = OSD.FromBinary(Convert.FromBase64String(reader.ReadString().Trim())); |
||
403 | break; |
||
404 | } |
||
405 | catch (FormatException ex) |
||
406 | { |
||
407 | throw new OSDException("Binary decoding exception: " + ex.Message); |
||
408 | } |
||
409 | } |
||
410 | |||
411 | ret = OSD.FromBinary(Utils.EmptyBytes); |
||
412 | break; |
||
413 | case "uri": |
||
414 | if (reader.IsEmptyElement) |
||
415 | { |
||
416 | reader.Read(); |
||
417 | return OSD.FromUri(new Uri(String.Empty, UriKind.RelativeOrAbsolute)); |
||
418 | } |
||
419 | |||
420 | if (reader.Read()) |
||
421 | { |
||
422 | ret = OSD.FromUri(new Uri(reader.ReadString(), UriKind.RelativeOrAbsolute)); |
||
423 | break; |
||
424 | } |
||
425 | |||
426 | ret = OSD.FromUri(new Uri(String.Empty, UriKind.RelativeOrAbsolute)); |
||
427 | break; |
||
428 | case "map": |
||
429 | return ParseLLSDXmlMap(reader); |
||
430 | case "array": |
||
431 | return ParseLLSDXmlArray(reader); |
||
432 | default: |
||
433 | reader.Read(); |
||
434 | ret = null; |
||
435 | break; |
||
436 | } |
||
437 | |||
438 | if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != type) |
||
439 | { |
||
440 | throw new OSDException("Expected </" + type + ">"); |
||
441 | } |
||
442 | else |
||
443 | { |
||
444 | reader.Read(); |
||
445 | return ret; |
||
446 | } |
||
447 | } |
||
448 | |||
449 | private static OSDMap ParseLLSDXmlMap(XmlTextReader reader) |
||
450 | { |
||
451 | if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map") |
||
452 | throw new NotImplementedException("Expected <map>"); |
||
453 | |||
454 | OSDMap map = new OSDMap(); |
||
455 | |||
456 | if (reader.IsEmptyElement) |
||
457 | { |
||
458 | reader.Read(); |
||
459 | return map; |
||
460 | } |
||
461 | |||
462 | if (reader.Read()) |
||
463 | { |
||
464 | while (true) |
||
465 | { |
||
466 | SkipWhitespace(reader); |
||
467 | |||
468 | if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map") |
||
469 | { |
||
470 | reader.Read(); |
||
471 | break; |
||
472 | } |
||
473 | |||
474 | if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key") |
||
475 | throw new OSDException("Expected <key>"); |
||
476 | |||
477 | string key = reader.ReadString(); |
||
478 | |||
479 | if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key") |
||
480 | throw new OSDException("Expected </key>"); |
||
481 | |||
482 | if (reader.Read()) |
||
483 | map[key] = ParseLLSDXmlElement(reader); |
||
484 | else |
||
485 | throw new OSDException("Failed to parse a value for key " + key); |
||
486 | } |
||
487 | } |
||
488 | |||
489 | return map; |
||
490 | } |
||
491 | |||
492 | private static OSDArray ParseLLSDXmlArray(XmlTextReader reader) |
||
493 | { |
||
494 | if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array") |
||
495 | throw new OSDException("Expected <array>"); |
||
496 | |||
497 | OSDArray array = new OSDArray(); |
||
498 | |||
499 | if (reader.IsEmptyElement) |
||
500 | { |
||
501 | reader.Read(); |
||
502 | return array; |
||
503 | } |
||
504 | |||
505 | if (reader.Read()) |
||
506 | { |
||
507 | while (true) |
||
508 | { |
||
509 | SkipWhitespace(reader); |
||
510 | |||
511 | if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array") |
||
512 | { |
||
513 | reader.Read(); |
||
514 | break; |
||
515 | } |
||
516 | |||
517 | array.Add(ParseLLSDXmlElement(reader)); |
||
518 | } |
||
519 | } |
||
520 | |||
521 | return array; |
||
522 | } |
||
523 | |||
524 | private static void SkipWhitespace(XmlTextReader reader) |
||
525 | { |
||
526 | while ( |
||
527 | reader.NodeType == XmlNodeType.Comment || |
||
528 | reader.NodeType == XmlNodeType.Whitespace || |
||
529 | reader.NodeType == XmlNodeType.SignificantWhitespace || |
||
530 | reader.NodeType == XmlNodeType.XmlDeclaration) |
||
531 | { |
||
532 | reader.Read(); |
||
533 | } |
||
534 | } |
||
535 | |||
536 | private static void CreateLLSDXmlSchema() |
||
537 | { |
||
538 | if (XmlSchema == null) |
||
539 | { |
||
540 | #region XSD |
||
541 | string schemaText = @" |
||
542 | <?xml version=""1.0"" encoding=""utf-8""?> |
||
543 | <xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema""> |
||
544 | <xs:import schemaLocation=""xml.xsd"" namespace=""http://www.w3.org/XML/1998/namespace"" /> |
||
545 | <xs:element name=""uri"" type=""xs:string"" /> |
||
546 | <xs:element name=""uuid"" type=""xs:string"" /> |
||
547 | <xs:element name=""KEYDATA""> |
||
548 | <xs:complexType> |
||
549 | <xs:sequence> |
||
550 | <xs:element ref=""key"" /> |
||
551 | <xs:element ref=""DATA"" /> |
||
552 | </xs:sequence> |
||
553 | </xs:complexType> |
||
554 | </xs:element> |
||
555 | <xs:element name=""date"" type=""xs:string"" /> |
||
556 | <xs:element name=""key"" type=""xs:string"" /> |
||
557 | <xs:element name=""boolean"" type=""xs:string"" /> |
||
558 | <xs:element name=""undef""> |
||
559 | <xs:complexType> |
||
560 | <xs:sequence> |
||
561 | <xs:element ref=""EMPTY"" /> |
||
562 | </xs:sequence> |
||
563 | </xs:complexType> |
||
564 | </xs:element> |
||
565 | <xs:element name=""map""> |
||
566 | <xs:complexType> |
||
567 | <xs:sequence> |
||
568 | <xs:element minOccurs=""0"" maxOccurs=""unbounded"" ref=""KEYDATA"" /> |
||
569 | </xs:sequence> |
||
570 | </xs:complexType> |
||
571 | </xs:element> |
||
572 | <xs:element name=""real"" type=""xs:string"" /> |
||
573 | <xs:element name=""ATOMIC""> |
||
574 | <xs:complexType> |
||
575 | <xs:choice> |
||
576 | <xs:element ref=""undef"" /> |
||
577 | <xs:element ref=""boolean"" /> |
||
578 | <xs:element ref=""integer"" /> |
||
579 | <xs:element ref=""real"" /> |
||
580 | <xs:element ref=""uuid"" /> |
||
581 | <xs:element ref=""string"" /> |
||
582 | <xs:element ref=""date"" /> |
||
583 | <xs:element ref=""uri"" /> |
||
584 | <xs:element ref=""binary"" /> |
||
585 | </xs:choice> |
||
586 | </xs:complexType> |
||
587 | </xs:element> |
||
588 | <xs:element name=""DATA""> |
||
589 | <xs:complexType> |
||
590 | <xs:choice> |
||
591 | <xs:element ref=""ATOMIC"" /> |
||
592 | <xs:element ref=""map"" /> |
||
593 | <xs:element ref=""array"" /> |
||
594 | </xs:choice> |
||
595 | </xs:complexType> |
||
596 | </xs:element> |
||
597 | <xs:element name=""llsd""> |
||
598 | <xs:complexType> |
||
599 | <xs:sequence> |
||
600 | <xs:element ref=""DATA"" /> |
||
601 | </xs:sequence> |
||
602 | </xs:complexType> |
||
603 | </xs:element> |
||
604 | <xs:element name=""binary""> |
||
605 | <xs:complexType> |
||
606 | <xs:simpleContent> |
||
607 | <xs:extension base=""xs:string""> |
||
608 | <xs:attribute default=""base64"" name=""encoding"" type=""xs:string"" /> |
||
609 | </xs:extension> |
||
610 | </xs:simpleContent> |
||
611 | </xs:complexType> |
||
612 | </xs:element> |
||
613 | <xs:element name=""array""> |
||
614 | <xs:complexType> |
||
615 | <xs:sequence> |
||
616 | <xs:element minOccurs=""0"" maxOccurs=""unbounded"" ref=""DATA"" /> |
||
617 | </xs:sequence> |
||
618 | </xs:complexType> |
||
619 | </xs:element> |
||
620 | <xs:element name=""integer"" type=""xs:string"" /> |
||
621 | <xs:element name=""string""> |
||
622 | <xs:complexType> |
||
623 | <xs:simpleContent> |
||
624 | <xs:extension base=""xs:string""> |
||
625 | <xs:attribute ref=""xml:space"" /> |
||
626 | </xs:extension> |
||
627 | </xs:simpleContent> |
||
628 | </xs:complexType> |
||
629 | </xs:element> |
||
630 | </xs:schema> |
||
631 | "; |
||
632 | #endregion XSD |
||
633 | |||
634 | MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(schemaText)); |
||
635 | |||
636 | XmlSchema = new XmlSchema(); |
||
637 | XmlSchema = XmlSchema.Read(stream, new ValidationEventHandler(LLSDXmlSchemaValidationHandler)); |
||
638 | } |
||
639 | } |
||
640 | |||
641 | private static void LLSDXmlSchemaValidationHandler(object sender, ValidationEventArgs args) |
||
642 | { |
||
643 | string error = String.Format("Line: {0} - Position: {1} - {2}", XmlTextReader.LineNumber, XmlTextReader.LinePosition, |
||
644 | args.Message); |
||
645 | |||
646 | if (LastXmlErrors == String.Empty) |
||
647 | LastXmlErrors = error; |
||
648 | else |
||
649 | LastXmlErrors += Environment.NewLine + error; |
||
650 | } |
||
651 | } |
||
652 | } |