Попытка решить ту же проблему. Я пришел к тому, что я считаю довольно чистым решением. Для ясности я пропустил некоторую проверку входных параметров.
Во-первых, сценарий : существует веб-служба, которая получает файл, который должен быть "правильно сформированным" xml и действительным для XSD. Разумеется, мы не верим ни «хорошей форме», ни тому, что в отношении XSD справедливо, что «мы знаем» является правильным.
Код для такого метода веб-сервиса представлен ниже, я думаю, он не требует пояснений.
Основной интерес представляет порядок, в котором происходит проверка, вы не проверяете пространство имен перед загрузкой, вы проверяете после, но чисто.
Я решил, что могу жить с некоторой обработкой исключений, так как ожидается, что большинство файлов будут "хорошими" и потому что это базовый способ работы (поэтому я не буду бороться с этим).
private DataTable xmlErrors;
[WebMethod]
public string Upload(byte[] f, string fileName) {
string ret = "This will have the response";
// this is the namespace that we want to use
string xmlNs = "http://mydomain.com/ns/upload.xsd";
// you could put a public url of xsd instead of a local file
string xsdFileName = Server.MapPath("~") + "//" +"shiporder.xsd";
// a simple table to store the eventual errors
// (more advanced ways possibly exist)
xmlErrors = new DataTable("XmlErrors");
xmlErrors.Columns.Add("Type");
xmlErrors.Columns.Add("Message");
try {
XmlDocument doc = new XmlDocument(); // create a document
// bind the document, namespace and xsd
doc.Schemas.Add(xmlNs, xsdFileName);
// if we wanted to validate if the XSD has itself XML errors
// doc.Schemas.ValidationEventHandler +=
// new ValidationEventHandler(Schemas_ValidationEventHandler);
// Declare the handler that will run on each error found
ValidationEventHandler xmlValidator =
new ValidationEventHandler(Xml_ValidationEventHandler);
// load the document
// will trhow XML.Exception if document is not "well formed"
doc.Load(new MemoryStream(f));
// Check if the required namespace is present
if (doc.DocumentElement.NamespaceURI == xmlNs) {
// Validate against xsd
// will call Xml_ValidationEventHandler on each error found
doc.Validate(xmlValidator);
if (xmlErrors.Rows.Count == 0) {
ret = "OK";
} else {
// return the complete error list, this is just to proove it works
ret = "File has " + xmlErrors.Rows.Count + " xml errors ";
ret += "when validated against our XSD.";
}
} else {
ret = "The xml document has incorrect or no namespace.";
}
} catch (XmlException ex) {
ret = "XML Exception: probably xml not well formed... ";
ret += "Message = " + ex.Message.ToString();
} catch (Exception ex) {
ret = "Exception: probably not XML related... "
ret += "Message = " + ex.Message.ToString();
}
return ret;
}
private void Xml_ValidationEventHandler(object sender, ValidationEventArgs e) {
xmlErrors.Rows.Add(new object[] { e.Severity, e.Message });
}
Теперь xsd будет выглядеть примерно так:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="shiporder"
targetNamespace="http://mydomain.com/ns/upload.xsd"
elementFormDefault="qualified"
xmlns="http://mydomain.com/ns/upload.xsd"
xmlns:mstns="http://mydomain.com/ns/upload.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:simpleType name="stringtype">
<xs:restriction base="xs:string"/>
</xs:simpleType>
...
</xs:schema>
А «хороший» XML будет выглядеть примерно так:
<?xml version="1.0" encoding="utf-8" ?>
<shiporder orderid="889923" xmlns="http://mydomain.com/ns/upload.xsd">
<orderperson>John Smith</orderperson>
<shipto>
<names>Ola Nordmann</names>
<address>Langgt 23</address>
Я тестировал, «неверный формат XML», «неверный ввод в соответствии с XSD», «неверное пространство имен».
ссылка:
Чтение из памяти
Попытка избежать обработки исключительных ситуаций для проверки работоспособности
При проверке XSD выявляются ошибки
Интересный пост о проверке встроенной схемы
Привет Мартин ,
раздел комментариев слишком короткий для моего ответа, поэтому я дам его здесь, это может быть или не быть полным ответом, давайте улучшим его вместе:)
Я сделал следующие тесты:
- Test: xmlns = "blaa"
- Результат: файл отклонен из-за неправильного пространства имен.
- Test: xmlns = "http://mydomain.com/ns/upload.xsd" и xmlns: a =" blaa ", а элементы имеют" a: someElement "
- Результат: ошибка при возврате файла говорит о том, что он не ожидает "a: someElement"
- Test: xmlns = "http://mydomain.com/ns/upload.xsd" и xmlns: a =" blaa ", а у элементов был элемент" someElement "с отсутствующим обязательным атрибутом
- Результат: файл возвращает ошибку о том, что атрибут отсутствует
Следовала стратегия (которую я предпочитаю): если документ не соответствует требованиям, не принять, но предоставить некоторую информацию о причине (например, "." неправильное пространство имен ").
Эта стратегия, кажется, противоречит тому, что вы ранее сказали:
однако, если клиент пропустит объявление пространства имен в представленном им XML, я хотел бы сказать, что мы все еще можем его проверить. Я не хочу просто сказать: «Вы все испортили, теперь исправьте!»
В этом случае кажется, что вы можете просто игнорировать определенное пространство имен в XML. Для этого вы должны пропустить проверку правильности пространства имен:
...
// Don't Check if the required namespace is present
//if (doc.DocumentElement.NamespaceURI == xmlNs) {
// Validate against xsd
// will call Xml_ValidationEventHandler on each error found
doc.Validate(xmlValidator);
if (xmlErrors.Rows.Count == 0) {
ret = "OK - is valid against our XSD";
} else {
// return the complete error list, this is just to proove it works
ret = "File has " + xmlErrors.Rows.Count + " xml errors ";
ret += "when validated against our XSD.";
}
//} else {
// ret = "The xml document has incorrect or no namespace.";
//}
...
Другие идеи ...
В параллельном плане, чтобы заменить предоставленное пространство имен своим, возможно, вы могли бы установить doc.DocumentElement.NamespaceURI = "mySpecialNamespace"
, заменяя таким образом пространство имен корневого элемента.
Ссылка :
добавить многодисковых пространств имен-к-корневой элемент