是的,我看了一下这个问题:Incorrect definition for the root element in XML schema
下面是我的代码示例,它加载XML并根据动态生成的XML模式进行检查。
问题是:当我添加一个生成为DOM文档对象的XML模式时,我收到一个错误:
EOleException:/ schema
XML模式中根元素的定义不正确
但是当我将XSD dom文档重新加载为字符串时:
xsd.loadXML(xsd.xml);
错误消失了。
我还制作了2个XSD调试输出:重载之前和之后。两个文件都是相同的字节到字节!
我不知道什么是错的,并假设当XML文档的字符串表示相同时,对象的结构也是相同的。
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.
问题是所有节点都没有namespaceURI
。它必须是http://www.w3.org/2001/XMLSchema
,并且不会为每个新节点自动设置它。
使用MSXML创建名称间隔元素并不容易。代码量三倍:
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.
更友好的版本:
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.