سؤال

وأنا أحاول للتحقق من صحة ملف 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top