首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将动态XML加载到数据集中

将动态XML加载到数据集中
EN

Stack Overflow用户
提问于 2016-02-15 14:56:11
回答 1查看 7.5K关注 0票数 0

我试图使用mydataset.loadfromfile("myfile.xml")将XML文件加载到dataset

问题是,我不知道XML字段名,也不知道它有多少字段。我知道XML只有一个级别,例如:

代码语言:javascript
复制
<DOCTO id ="3892" usuario="2" data="22/12/2015 10:33:22">
  <CONDUTA_1>teste conduta 1</CONDUTA_1>
  <CONDUTA_2>teste conduta 2</CONDUTA_2>
</DOCTO>

我正在寻找一种方法来加载xml,而不需要在前面创建字段。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-15 15:11:09

正如你说过你不能使用XMLMapper,我把答案的那一部分移到了底部。

由于不能使用XmlMapper,所以需要使用XML解析器自己解析XML。下面的示例使用Windows附带的XML,为此您需要在MSXML列表中使用Uses。为了说明如何做到这一点,我将使用与您的结构相同的XML,但是使用抽象的节点名称和属性名称,以避免XML的节点名称和值分散注意力。

代码语言:javascript
复制
<data a1="a" a2="b" a3="c">
  <r1>11111</r1>
  <r2>22222</r2>
</data>

在一个极端情况下,字段名可能是属性的名称a1、a2、a3,而字段值可能是这些属性值。

如何获得这些在LoadFromAttributes例程中显示。基本上,它将XML加载到XMLDoc对象中,使用XPath查询查找<data>节点,并获取其属性以创建dataset字段并设置其值。

在另一个极端,子节点<r1><r2>可能是字段名及其节点文本,字段值。LoadFromNodes例程展示了如何做到这一点。

当然,在实践中,XML的语义可能意味着字段名和值是这两者的混合体,但是由于您还没有提到XML的“含义”,所以我不得不留给您。

代码语言:javascript
复制
  TForm1 = class(TForm)
    Memo1: TMemo;
    CDS1: TClientDataSet;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    btnAttributes: TButton;
    btnFromNodes: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnAttributesClick(Sender: TObject);
    procedure btnFromNodesClick(Sender: TObject);
  public
    XMLDoc : IXMLDOMDocument;
    procedure PrepareCDS;
    procedure LoadFromAttributes;
    procedure LoadFromNodes;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  scXML =
     '<data a1="a" a2="b" a3="c">'#13#10
   + '  <r1>11111</r1>'#13#10
   + '  <r2>22222</r2>'#13#10
   + '</data>';

   scRootNodeName = 'data';

procedure TForm1.FormCreate(Sender: TObject);
begin
  XmlDoc := CoDOMDocument.Create;
  XmlDoc.Async := False;
  XMLDoc.loadXML(scXML);
  Memo1.Lines.Text := scXML;
end;

procedure TForm1.LoadFromAttributes;
var
  PathQuery : String;
  NodeList : IXmlDOMNodeList;
  Node,
  AttrNode : IXmlDomNode;
  Attributes : IXMLDOMNamedNodeMap;
  Field : TField;
  i : Integer;
begin
  PrepareCDS;

  PathQuery := scRootNodeName;
  NodeList := XMLDoc.SelectNodes(PathQuery);
  Assert(NodeList.Length > 0);
  Node := NodeList.item[0];
  Attributes := Node.attributes;
  for i := 0 to Attributes.Length - 1 do begin
    AttrNode := Attributes.item[i];
    Field := TStringField.Create(Self);
    Field.Size := 80;
    Field.FieldName := AttrNode.nodeName;
    Field.DataSet := CDS1;
  end;

  CDS1.CreateDataSet;

  CDS1.Insert;
  for i := 0 to Attributes.Length - 1 do begin
    AttrNode := Attributes.item[i];
    CDS1.Fields[i].Value := AttrNode.nodeValue;
  end;
  CDS1.Post;
end;

procedure TForm1.LoadFromNodes;
var
  PathQuery : String;
  NodeList : IXmlDOMNodeList;
  Node,
  AttrNode : IXmlDomNode;
  Field : TField;
  i : Integer;
begin
  PrepareCDS;

  PathQuery := scRootNodeName + '/*';
  NodeList := XMLDoc.SelectNodes(PathQuery);
  Assert(NodeList.Length > 0);
  for i := 0 to NodeList.Length - 1 do begin
    Node := NodeList.item[i];
    Field := TStringField.Create(Self);
    Field.Size := 80;
    Field.FieldName := Node.nodeName;
    Field.DataSet := CDS1;
  end;

  CDS1.CreateDataSet;

  CDS1.Insert;
  for i := 0 to NodeList.Length - 1 do begin
    Node := NodeList.item[i];
    CDS1.Fields[i].Value := Node.Text;
  end;
  CDS1.Post;
end;

procedure TForm1.PrepareCDS;
begin
  if CDS1.Active then
    CDS1.Close;
  CDS1.FieldDefs.Clear;
  CDS1.Fields.Clear;
end;

procedure TForm1.btnAttributesClick(Sender: TObject);
begin
  LoadFromAttributes;
end;

procedure TForm1.btnFromNodesClick(Sender: TObject);
begin
  LoadFromNodes;
end;

正如您所看到的,所有这些都非常简单,对MS解析器和XPath的使用稍微熟悉了一些(尽管在本例中,XML结构非常简单,您不需要使用XPath来实现它)。

在您的示例中,它不适用,但是如果提前修复了XML结构,则可以使用随Delphi附带的实用工具XmlMapper来定义映射文件,将其转换为TClientDataSet使用的格式。然后,可以将TClientDataSet与另一个组件TXmlTransformProvider结合使用,后者使用转换文件将数据加载到CDS中。详细情况如下:

Parsing xml file Delphi

顺便说一句,如果您的.Xml文件实际上有多个<DOCTO>节点,那么就需要将它们放在根节点下,以便文件具有有效的<DOCTO>结构。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35412477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档