I'm trying to validate an XML file against the schemas it references. (Using Delphi and MSXML2_TLB.) The (relevant part of the) code looks something like this:
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;
This has the result that cache is loaded (schemas.length > 0
), but then the next assignment raises an exception: "only XMLSchemaCache-schemacollections can be used."
How should I go about this?
I worked on the Miel´s solution to solve the disadventage. I open the xml twice, once to get the namespaces, and the other, after create the schema collection, to validate the file. It works for me. It seems like the IXMLDOMDocument2, once open, don´t accepts set the schemas property.
I have previously validated XML documents using the following code:
While BennyBechDk might be on the right track, I have a few problems with his code that I'm going to correct below:
If you wanted the system to just raise the exception, then there is no reason to make it a function in the first place.
Because validateDoc is an interface, it will be disposed of properly as the function/procedure exits, there is no need to perform the disposal yourself. If you call ValidateXmlDoc and don't get an exception then it is valid. Personally I like the first call, IsValidXMLDoc which returns true if valid or false if not (and does not raise exceptions outside of itself).
I've come up with an approach that seems to work. I first load the schema's explicitly, then add themn to the schemacollection. Next I load the xml-file and assign the schemacollection to its schemas property. The solution now looks like this:
It is important to use XMLSchemaCache40 or later. Earlier versions don't follow the W3C XML Schema standard, but only validate against XDR Schema, a MicroSoft specification.
The disadvantage of this solution is that I need to load the schema's explicitly. It seems to me that it should be possible to retrieve them automatically.