Если во время валидации xml требуется выполнять какие-то вычисления, запрашивать данные из БД, фиксировать Xpath к некорректному тегу и т.д. ... Решение:
| XmlElementReader reader = new XmlElementReader(); |
| reader.ProcessElement += delegate |
| | // для текущего элемента получить XPath и ... |
| | Trace.WriteLine(reader.GetXPath()); |
Код XmlElementReader'а приводится ниже. Работает он следующим образом: с помощью XmlReader'а читает теги, их атрибуты, а также использует стек для фиксации пути к текущему тегу. После это посылает событие ProcessElement.
| public class XmlElementReader |
| | public event EventHandler ProcessElement = delegate { }; |
| | public XmlElementReader() |
| | _Stack = new Stack<TagInfo>(); |
| | private Stack<TagInfo> _Stack; |
| | public void Read(string xmlPath) |
| | XmlReader r = XmlReader.Create(xmlPath); |
| | if (r.NodeType == XmlNodeType.Element) |
| | public TagInfo[] GetPath() |
| | return _Stack.ToArray().Reverse().ToArray(); |
| | [DebuggerDisplay("Name={Name}, Depth={Depth}, Index={Index}")] |
| | public string Name { get; set; } |
| | public int Index { get; set; } |
| | public int Depth { get; set; } |
| | public Dictionary<string, string> Attributes { get; set; } |
| | private void ReadElement(XmlReader xr) |
| | TagInfo stackTop = _Stack.Count > 0 ? _Stack.Peek() : null; |
| | if (stackTop == null || xr.Depth > stackTop.Depth) |
| | _Stack.Push(new TagInfo() { Name = xr.Name, Index = 0, Depth = xr.Depth, Attributes = xr.ReadAttributes() }); |
| | this.ProcessElement(this, EventArgs.Empty); |
| | if (xr.Depth < stackTop.Depth) |
| | this.ReadElement(xr); // рекурсия |
| | stackTop.Attributes = xr.ReadAttributes(); |
| | this.ProcessElement(this, EventArgs.Empty); |
| public static class XmlReaderHelper |
| | public static Dictionary<string, string> ReadAttributes(this XmlReader reader) |
| | Dictionary<string, string> ret = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); |
| | if (reader.HasAttributes) |
| | while (reader.MoveToNextAttribute()) |
| | ret.Add(reader.Name, reader.Value); |
| public static class XmlElementReaderHelper |
| | public static string GetXPath(this XmlElementReader reader) |
| | StringBuilder sb = new StringBuilder(); |
| | foreach (var ti in reader.GetPath()) |
| | if (ti.Attributes.TryGetValue("id", out id)) |
| | sb.Append("[@id='").Append(ti.Attributes["id"]).Append("']"); |
| | return sb.ToString().TrimEnd('/'); |
Комментариев нет:
Отправить комментарий