Link to home
Start Free TrialLog in
Avatar of Wim ten Brink
Wim ten BrinkFlag for Netherlands

asked on

[XML] Validating with MSXML

Okay, for the current project I am working on I can only use the MSXML type library that I've imported from C:\WINNT\system32\msxml3.dll and absolutely NOTHING ELSE! I am not looking for an alternative solution. I just need some functionality that works. Absolutely NO third-party components or libraries or whatever. Just a solution to get this code to work... (And I'm using Delphi 5 so don't start talking about the XML wizard of Delphi 7. I don't have any wizards and I don't need one either.)

Did you read the above? Fine. Here's the problem.

I have an XML file which needs to be validated. Thus I also have an XSD file that is linked to it. Basically, the XML file contains a list of topics, with several questions per topic and a possible answer per question. It looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Documents.xslt"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="D:\XML\Documents.xsd" LastUpdate="2004-11-12">
  <TopicGroup Name="EE Example">
    <Question Text="How to validate this file?">
      <Answer>I don't know...</Answer>
    </Question>
  </TopicGroup>
</Document>

And yes, there's also a stylesheet connected to this file. The stylesheet is what I will use to extract some specific data from the XML file and turn it into a HTML file. Not interesting either...

Okay, the Delphi code I have is very limited in what it can use. Basically just the ActiveX unit and the MSXML type library. It has to read the XML file, validate it with the XSD file then translate it with the XSLT file. Piece of cake, except for the validation...

uses
  Windows, SysUtils, ActiveX;

procedure TMyObject.Process;
var
  DOMDocument: IXMLDOMDocument2;
  HTMLDocument: IXMLDOMDocument2;
  StyleSheet: IXMLDOMDocument2;
  ParseError: IXMLDOMParseError;
begin
  // First create the documents I need.
  DOMDocument := CoDOMDocument.Create;
  HTMLDocument := CoDOMDocument.Create;
  StyleSheet := CoDOMDocument.Create;
  // We want to validate during parsing.
  DOMDocument.validateOnParse := True;
  // Load the XML file and the XSLT file.
  DOMDocument.load( 'D:\XML\Documents.xml' );
  StyleSheet.load( 'D:\XML\Documents.xslt' );
  // See if we got an error.
  ParseError := DOMDocument.parseError;
  if ( ParseError.errorCode <> 0 ) then ReportError( ParseError.reason );
  // For some reason, it went OK while I'm sure the XML file is NOT valid! (I made it invalid on purpose!)
  // Alternative method:
  ParseError := DOMDocument.validate;
  if ( ParseError.errorCode <> 0 ) then ReportError( ParseError.reason );
  // This just fails every time, saying: "Validate failed because the root element had no associated DTD/schema."
  // Oh, well. Transform the darned thing.
  HTMLDocument.loadXML( DOMDocument.transformNode( StyleSheet ) );
  HTMLDocument.save( 'D:\CVS\NetLeo\Documents\Documents.html' );
  // Well, that goes okay.

I know for sure the XML file is invalid yet MSXML claims it is not. (Or nags about the schema file.) Using XMLSpy, I made sure the contents of all files are as they should be. The schema and stylesheet are both valid and the XML file is just missing an attribute in one tag, making the rest valid.

If you're wondering what I'm trying to do here... I'm converting an XML file to XHTML here. Actually, there will be several transformations that I need to run on the XML file. Chances of invalid XML files is about 1 in 100, since sometimes, the process that generates the output gets killed before it has finished writing everything. (And in a rare occasion, it generates an invalid tag, but hey... I have no control over this other process.) My task is to make sure the file is valid (thus the schema) and then translate it. Preferably as fast as possible with a very small executable. Why? Because the executable will be located on a flash USB memory stick and the same stick will also have to contain the output file! (Yeah, it's a stupid method but hey... They only have to do this once per day so let them, okay?)

Maybe I should also load the Schema in an IXMLDOMDocument2 object and call some other function. Or whatever...

So, I can't spot my error. Who can?
Avatar of BigRat
BigRat
Flag of France image

Don't you need to set the Async property to false before loading the XML from a file?
Avatar of Wim ten Brink

ASKER

Set it to false, no effect.
Btw. For the transformation I now use IXSLTemplate and IXSLProcessor which provide me a more powerful way to do the transformation. I'm looking for a similar solution for validations...
Don't bother anymore. Solved the problem...
ASKER CERTIFIED SOLUTION
Avatar of Wim ten Brink
Wim ten Brink
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@RomMod,
I have left a message explaining that I found a solution and even provided the solution for future reference.

I wished the comment from BigRat had been of any use for me finding the solution but it wasn't even close. I am grateful for his attempt to try and help me though. But just being nice doesn't justify awarding points at EE...
>>I am grateful for his attempt to try and help me though.

   ... HER attempt....


No objections, RomMod.
Her? Oops, my mistake. Couldn't see that from here... :-)