التحقق من صحة المخطط مع MSXML في دلفي
سؤال
وأنا أحاول للتحقق من صحة ملف XML ضد مخططات فإنه يرجع. (عن طريق دلفي وMSXML2_TLB). و(الجزء ذي الصلة من) رمز يبدو شيئا من هذا القبيل:
procedure TfrmMain.ValidateXMLFile;
var
xml: IXMLDOMDocument2;
err: IXMLDOMParseError;
schemas: IXMLDOMSchemaCollection;
begin
xml := ComsDOMDocument.Create;
if xml.load('Data/file.xml') then
begin
schemas := xml.namespaces;
if schemas.length > 0 then
begin
xml.schemas := schemas;
err := xml.validate;
end;
end;
end;
وهذا يترتب عليه أن يتم تحميل ذاكرة التخزين المؤقت (schemas.length > 0
)، ولكن بعد ذلك احالة المقبل يثير استثناء: "فقط XMLSchemaCache-schemacollections يمكن استخدام"
وكيف يجب أن تذهب نحو هذا؟
المحلول
وجئت مع النهج الذي يبدو للعمل. أنا أولا تحميل مخطط صراحة، ثم يضاف themn إلى schemacollection. أنا القادم تحميل ملف XML وتعيين schemacollection بالممتلكات مخططات لها. الحل يبدو الآن مثل هذا:
uses MSXML2_TLB
That is:
// Type Lib: C:\Windows\system32\msxml4.dll
// LIBID: {F5078F18-C551-11D3-89B9-0000F81FE221}
function TfrmMain.ValidXML(
const xmlFile: String;
out err: IXMLDOMParseError): Boolean;
var
xml, xsd: IXMLDOMDocument2;
cache: IXMLDOMSchemaCollection;
begin
xsd := CoDOMDocument40.Create;
xsd.Async := False;
xsd.load('http://the.uri.com/schemalocation/schema.xsd');
cache := CoXMLSchemaCache40.Create;
cache.add('http://the.uri.com/schemalocation', xsd);
xml := CoDOMDocument40.Create;
xml.async := False;
xml.schemas := cache;
Result := xml.load(xmlFile);
if not Result then
err := xml.parseError
else
err := nil;
end;
ومن المهم استخدام XMLSchemaCache40 أو في وقت لاحق. الإصدارات السابقة لا تتبع معايير W3C XML مخطط، ولكن التحقق من صحة فقط ضد XDR مخطط مواصفات مايكروسوفت.
وعيوب هذا الحل هو أنني بحاجة إلى تحميل المخطط بشكل صريح. يبدو لي أنه ينبغي أن يكون من الممكن استردادها تلقائيا.
نصائح أخرى
وبينما قد يكون BennyBechDk على الطريق الصحيح، ولدي بعض المشاكل مع رمز له أنني ذاهب لتصحيح أدناه:
uses Classes, XMLIntf, xmlDoc, SysUtils;
function IsValidXMLDoc(aXmlDoc: IXMLDocument): boolean;
var
validateDoc: IXMLDocument;
begin
result := false; // eliminate any sense of doubt, it starts false period.
validateDoc := TXMLDocument.Create(nil);
try
validateDoc.ParseOptions := [poResolveExternals, poValidateOnParse];
validateDoc.XML := aXmlDoc.XML;
validateDoc.Active := true;
Result := True;
except
// for this example, I am going to eat the exception, normally this
// exception should be handled and the message saved to display to
// the user.
end;
end;
إذا أردت النظام لرفع مجرد استثناء، ثم ليس هناك ما يدعو إلى جعلها وظيفة في المقام الأول.
uses Classes, XMLIntf, XMLDoc, SysUtils;
procedure ValidateXMLDoc(aXmlDoc: IXMLDocument);
var
validateDoc: IXMLDocument;
begin
validateDoc := TXMLDocument.Create(nil);
validateDoc.ParseOptions := [poResolveExternals, poValidateOnParse];
validateDoc.XML := aXmlDoc.XML;
validateDoc.Active := true;
end;
ولأن validateDoc هو واجهة، سيتم التخلص منها بشكل صحيح كما هو إنهاء الدالة / الإجراء، ليست هناك حاجة لإجراء التخلص من نفسك. إذا كنت استدعاء ValidateXmlDoc وليس الحصول على استثناء فمن صالح. شخصيا أحب المكالمة الأولى، والتي ترجع IsValidXMLDoc صحيح اذا كان صحيحا أم خطأ إن لم يكن (ولا رفع استثناءات خارج نفسه).
وعملت على حل Miel's لحل disadventage. I فتح أكس مرتين، مرة للحصول على مساحات، والآخر، بعد إنشاء مجموعة مخطط، للتحقق من صحة الملف. بالنسبة لي كان يعمل. ويبدو أن IXMLDOMDocument2، مرة واحدة مفتوحة، لا تنزعج يقبل تعيين الخاصية المخططات.
function TForm1.ValidXML2(const xmlFile: String;
out err: IXMLDOMParseError): Boolean;
var
xml, xml2, xsd: IXMLDOMDocument2;
schemas, cache: IXMLDOMSchemaCollection;
begin
xml := CoDOMDocument.Create;
if xml.load(xmlFile) then
begin
schemas := xml.namespaces;
if schemas.length > 0 then
begin
xsd := CoDOMDocument40.Create;
xsd.Async := False;
xsd.load(schemas.namespaceURI[0]);
cache := CoXMLSchemaCache40.Create;
cache.add(schemas.namespaceURI[1], xsd);
xml2 := CoDOMDocument40.Create;
xml2.async := False;
xml2.schemas := cache;
Result := xml2.load(xmlFile);
//err := xml.validate;
if not Result then
err := xml2.parseError
else
err := nil;
end;
end;
ولقد التحقق من صحتها من قبل وثائق XML باستخدام التعليمات البرمجية التالية:
Uses
Classes,
XMLIntf,
SysUtils;
Function ValidateXMLDoc(aXmlDoc: IXMLDocument): boolean;
var
validateDoc: IXMLDocument;
begin
validateDoc := TXMLDocument.Create(nil);
validateDoc.ParseOptions := [poResolveExternals, poValidateOnParse];
validateDoc.XML := aXmlDoc.XML;
validateDoc.Active := true;
Result := True;
end;