2009-01-15 37 views
5

Tôi đang cố gắng xác thực tệp XML dựa trên tham chiếu của lược đồ đó. (Sử dụng Delphi và MSXML2_TLB.) The (phần liên quan của) mã trông giống như sau:xác thực lược đồ với msxml trong delphi

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; 

này có kết quả là bộ nhớ cache được nạp (schemas.length> 0), nhưng sau đó các nhiệm vụ tiếp theo đặt ra một ngoại lệ: "chỉ có thể sử dụng XMLSchemaCache-schemacollections."

Tôi nên làm như thế nào?

Cảm ơn, Miel.

Trả lời

5

Tôi đã đưa ra một cách tiếp cận có vẻ hoạt động. Lần đầu tiên tôi tải lược đồ một cách rõ ràng, sau đó thêm chúng vào lược đồ schemacollection. Tiếp theo, tôi tải tệp xml và gán tệp schemacollection cho thuộc tính lược đồ của nó. Bây giờ, giải pháp trông giống như sau:

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; 

Điều quan trọng là sử dụng XMLSchemaCache40 trở lên. Các phiên bản trước đó không tuân theo tiêu chuẩn Lược đồ XML của W3C, nhưng chỉ xác nhận hợp lệ đối với Lược đồ XDR, một đặc tả của MicroSoft.

Điểm bất lợi của giải pháp này là tôi cần tải giản đồ một cách rõ ràng. Dường như với tôi rằng nó sẽ có thể lấy chúng tự động.

+0

làm thế nào để bạn xác định xmlDoc? – neves

+0

xin lỗi, tôi nghĩ rằng nó phải là xml, chứ không phải xmlDoc. Chỉ để chắc chắn tôi sẽ kiểm tra trước khi tôi chỉnh sửa. – Miel

0

trước đây tôi đã xác nhận tài liệu XML bằng cách sử dụng đoạn mã sau:

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; 
1

Trong khi BennyBechDk có thể đi đúng hướng, tôi có một vài vấn đề với mã của mình rằng tôi sẽ sửa dưới đây:

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; 

Nếu bạn muốn hệ thống chỉ tăng ngoại lệ, thì không có lý do gì để đặt chức năng ở vị trí đầu tiên.

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; 

Bởi vì validateDoc là giao diện, nó sẽ được xử lý đúng như thoát khỏi chức năng/thủ tục, không cần phải tự mình xử lý. Nếu bạn gọi ValidateXmlDoc và không nhận được ngoại lệ thì nó hợp lệ. Cá nhân tôi thích cuộc gọi đầu tiên, IsValidXMLDoc trả về true nếu hợp lệ hoặc sai nếu không (và không nêu ngoại lệ bên ngoài chính nó).

+0

Tôi không thể làm việc này. Tôi nhận được lỗi "Số nhận dạng không được khai báo" cho TXMLDocument. Tôi có cần phải nhập một cái gì đó khác ngoài msxml để làm việc này không? – Miel

+0

Bạn cần sử dụng đơn vị XMLDoc. –

1

Tôi đã làm việc trong giải pháp của Miel để giải quyết tình trạng bất lợi. Tôi mở xml hai lần, một lần để có được các không gian tên, và cái kia, sau khi tạo bộ sưu tập lược đồ, để xác nhận hợp lệ tệp. Nó làm việc cho tôi. Dường như IXMLDOMDocument2, khi đã mở, không chấp nhận đặt thuộc tính lược đồ.

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; 
Các vấn đề liên quan