1 | using System.Xml;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System;
|
---|
4 | using System.Collections;
|
---|
5 | using System.IO;
|
---|
6 |
|
---|
7 | namespace Persistence {
|
---|
8 | public class XmlParser : IEnumerable<IParseToken> {
|
---|
9 |
|
---|
10 | private readonly XmlReader reader;
|
---|
11 | private delegate IEnumerator<IParseToken> Handler();
|
---|
12 | private readonly Dictionary<string, Handler> handlers;
|
---|
13 |
|
---|
14 | public XmlParser(TextReader input) {
|
---|
15 | XmlReaderSettings settings = new XmlReaderSettings {
|
---|
16 | ConformanceLevel = ConformanceLevel.Document,
|
---|
17 | IgnoreWhitespace = true,
|
---|
18 | IgnoreComments = true
|
---|
19 | };
|
---|
20 | reader = XmlReader.Create(input, settings);
|
---|
21 | handlers = new Dictionary<string, Handler> {
|
---|
22 | {"PRIMITIVE", ParsePrimitive},
|
---|
23 | {"COMPOSITE", ParseComposite},
|
---|
24 | {"REFERENCE", ParseReference},
|
---|
25 | {"NULL", ParseNull}
|
---|
26 | };
|
---|
27 | }
|
---|
28 | public IEnumerator<IParseToken> GetEnumerator() {
|
---|
29 | while (reader.Read()) {
|
---|
30 | if (!reader.IsStartElement()) {
|
---|
31 | break;
|
---|
32 | }
|
---|
33 | IEnumerator<IParseToken> iterator;
|
---|
34 | try {
|
---|
35 | iterator = handlers[reader.Name].Invoke();
|
---|
36 | }
|
---|
37 | catch (KeyNotFoundException) {
|
---|
38 | throw new InvalidOperationException(String.Format(
|
---|
39 | "No handler for XML tag \"{0}\" installed",
|
---|
40 | reader.Name));
|
---|
41 | }
|
---|
42 | while (iterator.MoveNext()) {
|
---|
43 | yield return iterator.Current;
|
---|
44 | }
|
---|
45 | }
|
---|
46 | }
|
---|
47 | private IEnumerator<IParseToken> ParsePrimitive() {
|
---|
48 | int? id = null;
|
---|
49 | string idString = reader.GetAttribute("id");
|
---|
50 | if (idString != null)
|
---|
51 | id = int.Parse(idString);
|
---|
52 | yield return new Primitive(
|
---|
53 | reader.GetAttribute("name"),
|
---|
54 | Type.GetType(reader.GetAttribute("type")),
|
---|
55 | reader.ReadString(),
|
---|
56 | id);
|
---|
57 | }
|
---|
58 | private IEnumerator<IParseToken> ParseComposite() {
|
---|
59 | string name = reader.GetAttribute("name");
|
---|
60 | Type type = Type.GetType(reader.GetAttribute("type"));
|
---|
61 | int id = int.Parse(reader.GetAttribute("id"));
|
---|
62 | yield return new CompositeStart(name, type, id);
|
---|
63 | IEnumerator<IParseToken> iterator = GetEnumerator();
|
---|
64 | while (iterator.MoveNext())
|
---|
65 | yield return iterator.Current;
|
---|
66 | yield return new CompositeEnd(name, type, id);
|
---|
67 | }
|
---|
68 | private IEnumerator<IParseToken> ParseReference() {
|
---|
69 | yield return new Reference(
|
---|
70 | reader.GetAttribute("name"),
|
---|
71 | int.Parse(reader.GetAttribute("ref")));
|
---|
72 | }
|
---|
73 | private IEnumerator<IParseToken> ParseNull() {
|
---|
74 | yield return new Null(reader.GetAttribute("name"));
|
---|
75 | }
|
---|
76 | IEnumerator IEnumerable.GetEnumerator() {
|
---|
77 | return GetEnumerator();
|
---|
78 | }
|
---|
79 | }
|
---|
80 | }
|
---|