문제

XML 파일을 Schemas IT 참조에 대해 검증하려고합니다. (Delphi 및 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-SCHEMACOLECTIOS 만 사용할 수 있습니다."

이것에 대해 어떻게 가야합니까?

도움이 되었습니까?

해결책

나는 작동하는 것처럼 보이는 접근 방식을 생각해 냈습니다. 먼저 스키마를 명시 적으로로드 한 다음 스키마 수집에 추가합니다. 다음으로 XML-File을로드하고 Schemacollection을 Schemas 속성에 할당합니다. 솔루션은 이제 다음과 같습니다.

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 스키마 표준을 따르지 않고 Microsoft 사양 인 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을 호출하고 예외가 없으면 유효합니다. 개인적으로 나는 유효한 경우 true를 반환하는 첫 번째 호출 인 isvalidxmldoc을 좋아합니다.

나는 단점을 해결하기 위해 Miel의 솔루션을 연구했습니다. 스키마 컬렉션을 만들어 네임 스페이스를 얻기 위해 XML을 두 번, 다른 하나는 파일을 검증하기 위해 네임 스페이스를 얻습니다. 그것은 나를 위해 작동합니다. IXMLDOMDOCUMENT2처럼 보이면 일단 열려 있으면 Schemas 속성을 설정하지 마십시오.

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