Yes, I took a look at this question: Incorrect definition for the root element in XML schema
Here is a sample of my code that loads XML and checks it against XML schema generated on the fly.
The problem is: when I add an XML schema generated as a DOM document object, I get an error:
EOleException: /schema
Incorrect definition for the root element in XML schema
but when I reload the XSD dom document into itself as a string:
xsd.loadXML(xsd.xml);
error disappears.
I made also 2 debug outputs of XSD: before reload and after. Both files are identical byte-to-byte!!!
I have no idea what could be wrong and assume that when string representations of XML documents are identical, then the objects' structures are identical too.
program XsdValidatorMCV;
uses
Winapi.MSXMLIntf, System.Win.ComObj, Winapi.ActiveX;
var
xsd: IXMLDOMDocument2;
xsdl: IXMLDOMSchemaCollection;
root: IXMLDOMElement;
el: IXMLDOMElement;
begin
CoInitialize(nil);
xsd := CreateOleObject('Msxml2.DOMDocument.6.0') as IXMLDOMDocument2;
xsdl := CreateOleObject('Msxml2.XMLSchemaCache.6.0') as IXMLDOMSchemaCollection;
try
xsd.appendChild(xsd.createProcessingInstruction('xml', 'version="1.0"'));
root := xsd.createElement('xs:schema');
root.setAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
xsd.appendChild(root);
el := xsd.createElement('xs:element');
root.appendChild(el);
el.setAttribute('name', 'data');
xsd.save('generated1.xsd'); //Debug output
//Workaround: reloading itself as string eliminates strange schema error:
//EOleException: /schema Incorrect definition for the root element in XML schema.
xsd.loadXML(xsd.xml);
xsd.save('generated2.xsd'); //Debug output
xsdl.add('', xsd); //Here is an error when without xsd.loadXML(xsd.xml)
finally
xsdl := nil;
xsd := nil;
end;
end.
The problem was the absence of namespaceURI
for all nodes. It must be http://www.w3.org/2001/XMLSchema
and it will not be set automatically for every new node.
Creating name-spaced elements with MSXML is not so easy. The amount of code triples:
const
NODE_ELEMENT = 1;
var
xsd: IXMLDOMDocument2;
xsdl: IXMLDOMSchemaCollection;
root: IXMLDOMNode;
el: IXMLDOMNode;
att: IXMLDOMAttribute;
begin
CoInitialize(nil);
xsd := CreateOleObject('Msxml2.DOMDocument.6.0') as IXMLDOMDocument2;
xsdl := CreateOleObject('Msxml2.XMLSchemaCache.6.0') as IXMLDOMSchemaCollection;
xsd.appendChild(xsd.createProcessingInstruction('xml', 'version="1.0"'));
root := xsd.createNode(NODE_ELEMENT, 'xs:schema', 'http://www.w3.org/2001/XMLSchema');
xsd.appendChild(root);
att := xsd.createAttribute('xmlns:xs');
att.value := 'http://www.w3.org/2001/XMLSchema';
root.attributes.setNamedItem(att);
el := xsd.createNode(NODE_ELEMENT, 'xs:element', 'http://www.w3.org/2001/XMLSchema');
root.appendChild(el);
att := xsd.createAttribute('name');
att.value := 'data';
el.attributes.setNamedItem(att);
xsdl.add('', xsd);
end.
More friendly version:
const
XS_URI = 'http://www.w3.org/2001/XMLSchema';
function createSchemaNode(const parentNode: IXMLDOMNode; const name: WideString): IXMLDOMNode;
const
NODE_ELEMENT = 1;
var
doc: IXMLDOMDocument;
begin
if Supports(parentNode, IXMLDOMDocument) then
doc := parentNode as IXMLDOMDocument
else
doc := parentNode.ownerDocument as IXMLDOMDocument;
Result := doc.createNode(NODE_ELEMENT, 'xs:' + name, XS_URI);
parentNode.appendChild(Result);
end;
procedure setAttribute(const node: IXMLDOMNode; const name: WideString; value: OleVariant);
var
att: IXMLDOMAttribute;
doc: IXMLDOMDocument2;
begin
doc := node.ownerDocument as IXMLDOMDocument2;
att := doc.createAttribute(name);
att.value := value;
node.attributes.setNamedItem(att);
end;
var
xsd: IXMLDOMDocument2;
xsdl: IXMLDOMSchemaCollection;
root: IXMLDOMNode;
el: IXMLDOMNode;
begin
CoInitialize(nil);
xsd := CreateOleObject('Msxml2.DOMDocument.6.0') as IXMLDOMDocument2;
xsdl := CreateOleObject('Msxml2.XMLSchemaCache.6.0') as IXMLDOMSchemaCollection;
xsd.appendChild(xsd.createProcessingInstruction('xml', 'version="1.0"'));
root := createSchemaNode(xsd, 'schema');
setAttribute(root, 'xmlns:xs', XS_URI);
el := createSchemaNode(root, 'element');
setAttribute(el, 'name', 'data');
xsdl.add('', xsd);
end.