XML数据绑定向导并使用多个名称空间

时间:2016-03-31 08:19:48

标签: xml delphi xsd xml-parsing

我正在尝试使用Delphi Seattle中的XML数据绑定向导为一组给定的XSD文件生成接口。我知道在XML向导中使用多个名称空间存在问题,但我不能让自己理解确切的问题/解决方案....

在向您提供详细信息之前,我的问题是:如何更改生成的代码,使其解释生成的XML中与XSD定义中不同的名称空间前缀?

生成代码的XSD如下

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="application/registration/2014/04" elementFormDefault="qualified"
    xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:rmrds="datamodel/canonical/datastructures/2014/01/">

    <import schemaLocation="CanonicalDataModel/CanonicalDataModel_DataStructures.xsd" namespace="datamodel/canonical/datastructures/2014/01/">
    </import>

    <element name="ApplicationInstanceRegistrationResponse">
        <complexType>
            <sequence>
                <element name="registrationResponse" type="rmrds:AppInstanceRegistrationType" />
            </sequence>
        </complexType>
    </element>
</schema>

此XSD使用以下内容引用数据结构命名空间:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="datamodel/canonical/datastructures/2014/01/"
    xmlns:rmrds="datamodel/canonical/datastructures/2014/01/" elementFormDefault="qualified"
    xmlns:rmrbt="datamodel/canonical/basetypes/2014/01/" xmlns:rmrst="datamodel/canonical/simpletypes/2014/01/">

    <import schemaLocation="CanonicalDataModel_BaseTypes.xsd" namespace="datamodel/canonical/basetypes/2014/01/" />
    <import schemaLocation="CanonicalDataModel_SimpleTypes.xsd" namespace="datamodel/canonical/simpletypes/2014/01/" />

    <complexType name="AppInstanceRegistrationType">
        <sequence>
            <element name="key" type="string" />
            <element name="secret" type="string" />
        </sequence>
    </complexType>
</schema>

注意:此XSD引用其他XSD,如basetypessimpletypes,但这些不在ApplicationregistrationType元素中使用,这是此处的问题

生成的代码如下所示(仅显示相关部分)

type

  IXMLApplicationInstanceRegistrationResponse = interface;
  IXMLAppInstanceRegistrationType_rmrds = interface;

  IXMLApplicationInstanceRegistrationResponse = interface(IXMLNode)
    ['{045B5E7C-83E2-4DB3-B7CD-7C2C28E0E387}']
    { Property Accessors }
    function Get_RegistrationResponse: IXMLAppInstanceRegistrationType_rmrds;
    { Methods & Properties }
    property RegistrationResponse: IXMLAppInstanceRegistrationType_rmrds read Get_RegistrationResponse;
  end;

  IXMLAppInstanceRegistrationType_rmrds = interface(IXMLNode)
    ['{2C1869A9-8B9E-4EC1-9320-5F6683BCB20E}']
    { Property Accessors }
    function Get_Key: String;
    function Get_Secret: String;
    procedure Set_Key(Value: String);
    procedure Set_Secret(Value: String);
    { Methods & Properties }
    property Key: String read Get_Key write Set_Key;
    property Secret: String read Get_Secret write Set_Secret;
  end;

  TXMLApplicationInstanceRegistrationResponse = class;
  TXMLAppInstanceRegistrationType_rmrds = class;

  TXMLApplicationInstanceRegistrationResponse = class(TXMLNode, IXMLApplicationInstanceRegistrationResponse)
  protected
    { IXMLApplicationInstanceRegistrationResponse }
    function Get_RegistrationResponse: IXMLAppInstanceRegistrationType_rmrds;
  public
    procedure AfterConstruction; override;
  end;

{ TXMLAppInstanceRegistrationType_rmrds }

  TXMLAppInstanceRegistrationType_rmrds = class(TXMLNode, IXMLAppInstanceRegistrationType_rmrds)
  protected
    { IXMLAppInstanceRegistrationType_rmrds }
    function Get_Key: String;
    function Get_Secret: String;
    procedure Set_Key(Value: String);
    procedure Set_Secret(Value: String);
  end;

{ Global Functions }

function GetApplicationInstanceRegistrationResponse(Doc: IXMLDocument): IXMLApplicationInstanceRegistrationResponse;
function LoadApplicationInstanceRegistrationResponse(const FileName: string): IXMLApplicationInstanceRegistrationResponse;
function NewApplicationInstanceRegistrationResponse: IXMLApplicationInstanceRegistrationResponse;

const
  TargetNamespace = 'application/registration/2014/04';

implementation

{ Global Functions }

function GetApplicationInstanceRegistrationResponse(Doc: IXMLDocument): IXMLApplicationInstanceRegistrationResponse;
begin
  Result := Doc.GetDocBinding('ApplicationInstanceRegistrationResponse', TXMLApplicationInstanceRegistrationResponse, TargetNamespace) as IXMLApplicationInstanceRegistrationResponse;
end;

function LoadApplicationInstanceRegistrationResponse(const FileName: string): IXMLApplicationInstanceRegistrationResponse;
begin
  Result := LoadXMLDocument(FileName).GetDocBinding('ApplicationInstanceRegistrationResponse', TXMLApplicationInstanceRegistrationResponse, TargetNamespace) as IXMLApplicationInstanceRegistrationResponse;
end;

function NewApplicationInstanceRegistrationResponse: IXMLApplicationInstanceRegistrationResponse;
begin
  Result := NewXMLDocument.GetDocBinding('ApplicationInstanceRegistrationResponse', TXMLApplicationInstanceRegistrationResponse, TargetNamespace) as IXMLApplicationInstanceRegistrationResponse;
end;

{ TXMLApplicationInstanceRegistrationResponse }

procedure TXMLApplicationInstanceRegistrationResponse.AfterConstruction;
begin
  RegisterChildNode('registrationResponse', TXMLAppInstanceRegistrationType_rmrds);
  inherited;
end;

function TXMLApplicationInstanceRegistrationResponse.Get_RegistrationResponse: IXMLAppInstanceRegistrationType_rmrds;
begin
  Result := ChildNodes['registrationResponse'] as IXMLAppInstanceRegistrationType_rmrds;
end;

{ TXMLAppInstanceRegistrationType_rmrds }

function TXMLAppInstanceRegistrationType_rmrds.Get_Key: String;
begin
  Result := ChildNodes['key'].NodeValue;
end;

procedure TXMLAppInstanceRegistrationType_rmrds.Set_Key(Value: String);
begin
  ChildNodes['key'].NodeValue := Value;
end;

function TXMLAppInstanceRegistrationType_rmrds.Get_Secret: String;
begin
  Result := ChildNodes['secret'].NodeValue;
end;

procedure TXMLAppInstanceRegistrationType_rmrds.Set_Secret(Value: String);
begin
  ChildNodes['secret'].NodeValue := Value;
end;
end.

REST服务为我提供了以下答案XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns10:ApplicationInstanceRegistrationResponse 
   xmlns="datamodel/financial/modelobjects/2014/01/"
   xmlns:ns3="canonical/basetypes/2014/01/"
   xmlns:ns5="datamodel/canonical/datastructures/2014/01/"
   xmlns:ns6="datamodel/canonical/simpletypes/2014/01/" 
   xmlns:ns10="application/registration/2014/04" 

  <ns10:registrationResponse>
    <ns5:key>cac7bacc</ns5:key>
    <ns5:secret>NzY2MDkwNzliNjJkZTE1MWRjNGViNTI4MTk4MmZjZDkzYzhmY2UwNDA5YmJhMjlhYzVlY2JjZGFmNWE1NDg2OA==</ns5:secret>
  </ns10:registrationResponse>
</ns10:ApplicationInstanceRegistrationResponse>

当我创建一个GetApplicationInstanceRegistrationResponse(XML)试图获取Key或Secret值的实例时会出现OLEVariant错误,因为ChildNodes['key']中的TXMLAppInstanceRegistrationType_rmrds.Get_Key语句找不到该节点。当我使用ChildNodes['ns5:key']时,它可以工作,但ns5不是固定的名称空间前缀。

我已经接受了向导生成的代码必须手动更改,因为网上的广泛搜索没有为我提供修复向导结果的任何结构解决方案。

那么如何解决这个问题并使TXMLAppInstanceRegistrationType_rmrds知道其元素是在datastructure模式中定义的?

0 个答案:

没有答案