Đang cố gắng để giải quyết cùng một vấn đề. Tôi nghĩ ra một giải pháp khá sạch sẽ. Để rõ ràng, tôi đã ommited một số xác nhận về các tham số đầu vào.
Đầu tiên, trường hợp: Có một dịch vụ web nhận tệp, được cho là "xml" hợp lệ và hợp lệ đối với XSD. Tất nhiên, chúng tôi không tin tưởng vào "tính đúng đắn" cũng như không hợp lệ với XSD mà "chúng tôi biết" là chính xác.
Mã cho phương pháp webservice như vậy được trình bày bên dưới, tôi nghĩ nó tự giải thích.
Điểm quan tâm chính là thứ tự mà các xác thực đang diễn ra, bạn không kiểm tra không gian tên trước khi tải, bạn kiểm tra sau, nhưng sạch sẽ.
Tôi quyết định tôi có thể sống với một số xử lý ngoại lệ, vì dự kiến hầu hết các tệp sẽ "tốt" và vì đó là cách xử lý khuôn khổ (vì vậy tôi sẽ không đánh với nó).
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 });
}
Bây giờ, xsd sẽ có somthing như:
<?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>
Và "tốt" XML sẽ là một cái gì đó như:
<?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>
tôi thử nghiệm "định dạng XML xấu", "đầu vào không hợp lệ theo XSD", "không gian tên không chính xác".
tham khảo:
Read from memorystream
Trying avoid exception handling checking for wellformness
Validating against XSD, catch the errors
Interesting post about inline schema validation
Hi Martin, nhận xét sction là quá ngắn cho câu trả lời của tôi, vì vậy tôi sẽ cung cấp cho nó ở đây, nó có thể hoặc không thể là một câu trả lời hoàn chỉnh, chúng ta hãy cùng nhau cải thiện nó :)
tôi đã thực hiện các bài kiểm tra sau :
- Test: xmlns = "blaa"
- Kết quả: các tập tin bị từ chối, vì không gian tên sai.
- Kiểm tra: xmlns = "http://mydomain.com/ns/upload.xsd" và xmlns: a = "blaa" và các thành phần có "a: someElement"
- Kết quả: Lỗi trả về tệp cho biết không mong đợi "a: someElement"
- Kiểm tra: xmlns = "http://mydomain.com/ns/upload.xsd" và xmlns: a = "blaa" và các phần tử có "someElement" với một số thuộc tính bắt buộc bị thiếu
- Kết quả: các lỗi trở về tập tin nói rằng thuộc tính là mất tích
các chiến lược sau (mà tôi thích) là, nếu d ocument không tuân thủ, sau đó không chấp nhận, nhưng cung cấp một số thông tin về lý do (ví dụ: "không gian tên sai").
Chiến lược này dường như trái với những gì bạn nói trước đây:
Tuy nhiên, nếu một khách hàng bỏ sót việc kê khai không gian tên trong XML trình của họ sau đó tôi muốn nói rằng chúng ta vẫn có thể xác nhận nó. Tôi không muốn chỉ nói "Bạn đã sai lầm, bây giờ sửa nó!"
Trong trường hợp này, có vẻ như bạn chỉ có thể bỏ qua không gian tên được xác định trong XML. Để làm điều đó bạn sẽ bỏ qua xác nhận của đúng namespace:
...
// 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.";
//}
...
ý tưởng khác ...
Trong một đường song song tư tưởng, để thay thế cho tên miền không gian được cung cấp bằng cách riêng của bạn, có lẽ bạn có thể thiết lập doc.DocumentElement.NamespaceURI = "mySpecialNamespace"
do đó thay thế các namepsace của phần tử gốc.
Reference:
add-multiple-namespaces-to-the-root-element
Vùng tên XML là một điều tốt, tại sao lại chống lại nó? –
đó là điều chúng tôi không thể kiểm soát, tôi muốn đảm bảo rằng khách hàng đang gửi đúng XML, tuy nhiên, nếu khách hàng bỏ lỡ khai báo không gian tên trong XML đã gửi của họ thì tôi muốn nói rằng chúng tôi vẫn có thể xác thực nó. Tôi không muốn chỉ nói "Bạn đã sai lầm, bây giờ sửa nó!" (và vâng tôi sẽ sử dụng các từ tốt hơn, nhưng bạn có ý tưởng). – Martin