2009-01-15 9 views
5

मैं स्कीमा के संदर्भों के विरुद्ध एक एक्सएमएल फ़ाइल को सत्यापित करने की कोशिश कर रहा हूं। (डेल्फी और MSXML2_TLB का उपयोग करना।) कोड (के प्रासंगिक भाग) इस तरह दिखता है:डेल्फी में msxml के साथ स्कीमा सत्यापन

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 का उपयोग किया जा सकता है।"

मुझे इसके बारे में कैसे जाना चाहिए?

धन्यवाद, मील।

उत्तर

5

मैं काम करने के लिए एक दृष्टिकोण के साथ आया हूं। मैं पहले स्कीमा को स्पष्ट रूप से लोड करता हूं, फिर स्कीमकोलेक्शन में उन्हें जोड़ता हूं। इसके बाद मैं xml-file लोड करता हूं और स्कीमकोलेक्शन को अपनी स्कीमा प्रॉपर्टी में असाइन करता हूं। समाधान अब इस तरह दिखता है:

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 या बाद में उपयोग करना महत्वपूर्ण है। पहले के संस्करण डब्लू 3 सी एक्सएमएल स्कीमा मानक का पालन नहीं करते हैं, लेकिन केवल माइक्रोसॉफ़्ट विनिर्देशन एक्सडीआर स्कीमा के खिलाफ मान्य हैं।

इस समाधान का नुकसान यह है कि मुझे स्कीमा को स्पष्ट रूप से लोड करने की आवश्यकता है। ऐसा लगता है कि उन्हें स्वचालित रूप से पुनर्प्राप्त करना संभव होना चाहिए।

+0

आप xmlDoc को कैसे परिभाषित करते हैं? – neves

+0

क्षमा करें, मुझे लगता है कि यह xml होना चाहिए, xmlDoc नहीं। बस यह सुनिश्चित करने के लिए कि मैं संपादित करने से पहले जांच करूंगा। – Miel

0

मैं पहले निम्नलिखित कोड का उपयोग कर 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; 
1

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 जो वैध या गलत अगर सही नहीं है (और स्वयं के बाहर अपवाद नहीं उठाता है)।

+0

मैं इसे काम पर नहीं ला सकता। मुझे TXMLDocument के लिए "Undeclared पहचानकर्ता" त्रुटि मिलती है। क्या मुझे काम करने के लिए एमएसएक्सएमएल के अलावा कुछ और आयात करने की ज़रूरत है? – Miel

+0

आपको XMLDoc इकाई का भी उपयोग करने की आवश्यकता है। –

1

मैंने विद्रोह को हल करने के लिए मिएल के समाधान पर काम किया। मैं नाम को प्राप्त करने के लिए, स्कीमा संग्रह बनाने के बाद, फ़ाइल को सत्यापित करने के लिए, xml को दो बार खोलता हूं। इससे मेरा काम बनता है। ऐसा लगता है कि 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;