Как лучше всего проверить достоверность XML с помощью метода?
-
02-07-2019 - |
Вопрос
У меня есть несколько методов WCF, которые используются для передачи информации из серверного приложения во внешний интерфейс веб-сайта для использования при привязке.Я отправляю результат как XElement, который является корнем XML-дерева, содержащего данные, с которыми я хочу выполнить привязку.
Я хотел бы создать несколько тестов, которые проверят данные и проверят, что они соответствуют ожиданиям.
Мои текущие мысли таковы:Каждый метод, возвращающий дерево XElement, имеет соответствующий файл схемы (.XSD).Этот файл включен в сборку, содержащую мои классы WCF в качестве встроенного ресурса.
Тесты вызывают метод этих методов и сравнивают результат с этими встроенными схемами.
Это хорошая идея?Если нет, то какие еще способы я могу использовать, чтобы обеспечить «гарантию» того, какой тип XML вернет метод?
Если да, то как проверить XElement на соответствие схеме?И как я могу получить эту схему из сборки, в которую она встроена?
Решение
Я бы сказал, что проверка XML с помощью схемы xsd — хорошая идея.
Как проверить XElement с загруженной схемой:Как вы видите в этом примере, вам необходимо сначала проверить XDocument, чтобы заполнить «информационный набор после проверки схемы» (возможно, существует решение сделать это без использования метода Validate в XDOcument, но я еще не нашел его):
String xsd =
@"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:element name='root'>
<xsd:complexType>
<xsd:sequence>
<xsd:element name='child1' minOccurs='1' maxOccurs='1'>
<xsd:complexType>
<xsd:sequence>
<xsd:element name='grandchild1' minOccurs='1' maxOccurs='1'/>
<xsd:element name='grandchild2' minOccurs='1' maxOccurs='2'/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>";
String xml = @"<?xml version='1.0'?>
<root>
<child1>
<grandchild1>alpha</grandchild1>
<grandchild2>beta</grandchild2>
</child1>
</root>";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsd)));
XDocument doc = XDocument.Load(XmlReader.Create(new StringReader(xml)));
Boolean errors = false;
doc.Validate(schemas, (sender, e) =>
{
Console.WriteLine(e.Message);
errors = true;
}, true);
errors = false;
XElement child = doc.Element("root").Element("child1");
child.Validate(child.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
{
Console.WriteLine(e.Message);
errors = true;
});
Как прочитать внедренную схему из сборки и добавить ее в XmlSchemaSet:
Assembly assembly = Assembly.GetExecutingAssembly();
// you can use reflector to get the full namespace of your embedded resource here
Stream stream = assembly.GetManifestResourceStream("AssemblyRootNamespace.Resources.XMLSchema.xsd");
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, XmlReader.Create(stream));
Другие советы
Если вы выполняете какую-то легкую работу и XSD излишни, рассмотрите возможность строгой типизации XML-данных.Например, в моем проекте есть несколько классов, производных от XElement.Один — ExceptionXElement, другой — HttpHeaderXElement и т. д.В них я наследую XElement и добавляю методы Parse и TryParse, которые принимают строки, содержащие данные XML, для создания экземпляра.Если TryParse() возвращает false, строка не соответствует ожидаемым мной XML-данным (корневой элемент имеет неправильное имя, отсутствуют дочерние элементы и т. д.).
Например:
public class MyXElement : XElement
{
public MyXElement(XElement element)
: base(element)
{ }
public static bool TryParse(string xml, out MyXElement myElement)
{
XElement xmlAsXElement;
try
{
xmlAsXElement = XElement.Parse(xml);
}
catch (XmlException)
{
myElement = null;
return false;
}
// Use LINQ to check if xmlAsElement has correct nodes...
}