Есть код для проверки XML файла по XSD-схеме:
public static void ValidateAgainstSchema(string XMLSourceDocument, XmlSchemaSet validatingSchemas)
{
if (validatingSchemas == null)
{
throw new ArgumentNullException("In ValidateAgainstSchema: No schema loaded.");
}
string errorHolder = string.Empty;
ValidationHandler handler = new ValidationHandler();
XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(handler.HandleValidationError);
settings.Schemas.Add(validatingSchemas);
settings.ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation;
StringReader srStringReader = new StringReader(XMLSourceDocument);
XmlReader validatingReader = XmlReader.Create(srStringReader, settings);
try
{
while (validatingReader.Read())
{
}
}
catch (XmlException ex)
{
Console.WriteLine("XMLException occurred: " + ex.Message);
}
if (handler.MyValidationErrors.Count > 0)
{
foreach (String messageItem in handler.MyValidationErrors)
{
errorHolder += messageItem;
}
//throw new XmlSchemaValidationException(errorHolder);
}
Console.WriteLine(errorHolder);}
public class ValidationHandler
{
private IList<string> myValidationErrors = new List<String>();
public IList<string> MyValidationErrors { get { return this.myValidationErrors; } }
public void HandleValidationError(object sender, ValidationEventArgs ve)
{
if (ve.Severity == XmlSeverityType.Error || ve.Severity == XmlSeverityType.Warning)
{
this.myValidationErrors.Add(
String.Format(
Environment.NewLine + "Line: {0}, Position {1}: \"{2}\"",
ve.Exception.LineNumber,
ve.Exception.LinePosition,
ve.Exception.Message)
);
}
}
}
который выводит слудующую инфу об ошибках в xml-файле:
Line: 4, Position 20: "Элемент "foo" имеет недопустимый дочерний элемент "baz". Список ожидаемых элементов: "bar"."
Line: 13, Position 20: "Элемент "foo" имеет недопустимый дочерний элемент "baz". Список ожидаемых элементов: "bar"."
Как видно, благодаря свойствам LineNumber, LinePosition можно получить инфу о позиции каждой ошибки, но как получить имя элемента xml, в котором обнаружена ошибка, а также имя его родителя?
Чтобы было легче воспринимать, я упростил код до следующего:
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
namespace ConApp1
{
class Program
{
static Stack<string> stack = new Stack<string>();
static string previous;
static int depth;
static void Main(string[] args)
{
try
{
var schemaSet = new XmlSchemaSet();
schemaSet.Add("", "test.xsd");
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += Settings_ValidationEventHandler;
settings.Schemas.Add(schemaSet);
using (var reader = XmlReader.Create("test.xml", settings))
{
while (reader.Read())
{
if (reader.NodeType != XmlNodeType.Whitespace)
{
previous = reader.Name;
}
if (reader.NodeType == XmlNodeType.Element)
{
if (depth == reader.Depth)
{
stack.Push(reader.Name);
depth++;
}
}
else if (reader.NodeType == XmlNodeType.EndElement)
{
stack.Pop();
depth--;
}
}
}
}
catch (Exception e) { Console.WriteLine(e.Message); }
}
private static void Settings_ValidationEventHandler(object sender, ValidationEventArgs e)
{
Console.WriteLine(string.Join(", ", stack));
Console.WriteLine(previous);
Console.WriteLine("Line: {0}, Position {1}: \"{2}\"",
e.Exception.LineNumber, e.Exception.LinePosition, e.Exception.Message);
}
}
}
Здесь в поле previous
запоминается имя элемента, непосредственно предшествующего тому, в котором произошла ошибка валидации.
А в стеке хранятся все родительские элементы, от текущего до корня.
Аналогичным образом можно сохранять в коллекции любую необходимую информацию.
Для такого xml:
<?xml version="1.0"?>
<root>
<foo>
<bar/>
<bar/>
</foo>
<foo>
<bar/>
<bar/>
</foo>
</root>
была создана такая схема:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="foo">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="bar" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Если теперь внести ошибку: заменить последний элемент bar
на baz
, получим следующий вывод:
bar, foo, root
bar
То есть мы имеем все родительские элементы и предыдущий элемент.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть динамический список, который добавляет объекты по их idИмя так же
Не получается подключиться удаленно к mysql серверу
В бд хранится данные в формате json, вот так выглядят {"0,2,,,,,,,,,,,,,,": ""} Мне нужно получить их и записать в массив js