在动态生成XSD时,XML模式中根元素的定义不正确

问题描述 投票:2回答:1

是的,我看了一下这个问题: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.
xml delphi xsd msxml6
1个回答
1
投票

问题是所有节点都没有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.
© www.soinside.com 2019 - 2024. All rights reserved.