Frage

Ich versuche, eine XML-Datei gegen das Schema zu validieren es verweist. (Mit Delphi und MSXML2_TLB.) Der (relevante Teil des) Code sieht etwa so aus:

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;

Dies hat zur Folge, dass Cache geladen wird (schemas.length > 0), aber dann ist die nächste Aufgabe löst eine Ausnahme: „nur XMLSchemaCache-schemacollections verwendet werden kann“

Wie soll ich über diese gehen?

War es hilfreich?

Lösung

Ich habe mit einem Ansatz kommen, die zu funktionieren scheint. Ich lade zuerst das Schema der explizit, dann zum schemacollection hinzufügen themn. Ich lade Weiter, um die XML-Datei und die schemacollection seines Schema Eigenschaft zuweisen. Die Lösung sieht nun wie folgt aus:

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;

Es ist wichtig, XMLSchemaCache40 oder später zu verwenden. Frühere Versionen des W3C XML Schema-Standard nicht folgen, sondern nur validieren gegen XDR-Schema, eine Microsoft-Spezifikation.

Der Nachteil dieser Lösung ist, dass ich ausdrücklich das Schema des laden. Es scheint mir, dass es möglich sein sollte, sie automatisch abgerufen werden.

Andere Tipps

Während BennyBechDk auf dem richtigen Weg sein könnte, habe ich ein paar Probleme mit seinem Code, den ich unten korrigieren werde:

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;

Wenn Sie das System wollten nur die Ausnahme auslösen, dann gibt es keinen Grund, warum es eine Funktion in erster Linie zu machen.

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;

Da validateDoc eine Schnittstelle ist, wird es von richtig, wie die Funktion / Prozedur beendet entsorgt wird, gibt es keine Notwendigkeit, die Entsorgung selbst auszuführen. Wenn Sie ValidateXmlDoc anrufen und nicht eine Ausnahme erhalten, dann ist es gültig. Persönlich mag ich den ersten Anruf, IsValidXMLDoc die, wenn sie gültig oder falsch true zurück, wenn nicht (und nicht erhöhen Ausnahmen außerhalb von selbst).

ich arbeitete an der Miel's Lösung die disadventage zu lösen. Ich öffne die xml zweimal, einmal die Namensräume zu bekommen, und die andere, nach dem Schema Sammlung erstellen, um die Datei zu validieren. Für mich geht das. Es scheint, wie die IXMLDOMDocument2, einmal geöffnet, DO NOT den Schemata Eigenschaft akzeptiert.

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;

Ich habe vorher validierte XML-Dokumente mit dem folgenden Code:

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top