【问题标题】:How to use query on XML file in Delphi?如何在 Delphi 中对 XML 文件使用查询?
【发布时间】:2013-07-09 19:27:46
【问题描述】:

我是 Delphi 的新手,这就是我想做的事情。我有这样格式的 XML 文件,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Row>
        <Designation>1234102</Designation>
        <Inner>5.412</Inner>
        <Outer>3.588</Outer>
        <Spin>4.732</Spin>
        <Cage>0.399</Cage>
    </Row>
    <Row>
        <Designation>1342153</Designation>
        <Inner>5.916</Inner>
        <Outer>4.084</Outer>
        <Spin>5.277</Spin>
        <Cage>0.408</Cage>
    </Row>
    ........
</Data>

我想用 Delphi 查询它。例如:我想要 1342153 在哪里的数据。最好和最简单的解决方案是什么?

提前感谢示例和解释。

【问题讨论】:

  • 查询是什么意思?为什么你需要那个值而不是其他值?你还会想要其他值吗?它们中的哪一个,为什么以及频率如何?可能有几种解决方案,如 DOM 解析器、SAX 解析器、XPATH、记录数组反序列化 - 但不知道您实际上需要对 XML 做什么。 catb.org/esr/faqs/smart-questions.html
  • 也请编辑您的问题,并在文本下方添加您的特定 delphi 语言版本的标签
  • 我的 XML 大约有 6000 个“行”,我想阅读整行而不仅仅是名称。

标签: xml delphi


【解决方案1】:

我假设一旦找到Designation,您还想阅读其他条目(InnerOuterSpinCage)与名称相符。

XPath 是这个问题的完美解决方案。我的示例使用了一个新表单,上面只放置了一个 TMemoTButton,并为 Button1.OnClick 事件添加了一个处理程序:

uses
  MSXML, ComObj, ActiveX;

const
  XMLText =  '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
             '<Data>' +
              '<Row>' +
                  '<Designation>1234102</Designation>' +
                  '<Inner>5.412</Inner>' +
                  '<Outer>3.588</Outer>' +
                  '<Spin>4.732</Spin>' +
                  '<Cage>0.399</Cage>' +
              '</Row>' +
              '<Row>' +
                 '<Designation>1342153</Designation>' +
                 '<Inner>5.916</Inner>' +
                  '<Outer>4.084</Outer>' +
                  '<Spin>5.277</Spin>' +
                  '<Cage>0.408</Cage>' +
              '</Row>' +
          '</Data>';

procedure TForm1.Button1Click(Sender: TObject);
var
  XMLDoc: IXMLDOMDocument;
  Node, SibNode: IXMLDOMNode;
begin
  Memo1.Clear;
  XMLDoc := CoDOMDocument.Create;
  XMLDoc.loadXML(XMLText);

  // Select the node with the Designation you want.
  Node := XMLDoc.selectSingleNode('//Designation[text()="1342153"]');
  if Assigned(Node) then
  begin
    Memo1.Lines.Add('Found it.');
    Memo1.Lines.Add(Node.nodeName + ' = ' + Node.firstChild.nodeValue);

    // Read all the nodes at the same level as the Designation
    SibNode := Node.nextSibling;
    while SibNode <> nil do
    begin
      Memo1.Lines.Add(SibNode.nodeName + ' = ' + 
                      SibNode.firstChild.nodeValue);
      Sib := Sib.nextSibling;
    end;
  end;
end;

如果您只想获取所有 &lt;Row&gt; 元素,并遍历它们包含的信息,您可以使用这个(在上面的测试应用程序中添加第二个按钮,并将其用于 Button2.OnClick 处理程序) :

procedure TForm1.Button2Click(Sender: TObject);
var
  XMLDoc: IXMLDOMDocument;
  NodeList: IXMLDOMNodeList;
  Node, SibNode: IXMLDOMNode;
  i: Integer;
begin
  Memo1.Clear;
  XMLDoc := CoDOMDocument.Create;
  XMLDoc.loadXML(XMLText);
  NodeList := XMLDoc.selectNodes('/Data/Row');
  if Assigned(NodeList) then
  begin
    for i := 0 to NodeList.length - 1 do
    begin
      Node := NodeList.item[i];
      SibNode := Node.firstChild;
      while Assigned(SibNode) do
      begin
        Memo1.Lines.Add(SibNode.nodeName + ' = ' + 
                        SibNode.firstChild.nodeValue);
        SibNode := SibNode.nextSibling;
      end;
    end;
    // Add a blank line between groupings for readability
    Memo1.Lines.Add('');
  end;
end;

【讨论】:

    【解决方案2】:

    正如其他人建议的那样,您可以使用 XPath 来查找特定值,在这种情况下,使用此表达式 /Data/Row/Designation[text()="1342153"] 将在指定中找到包含值 1342153 的节点。

    试试这个示例代码

    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      MSXML,
      SysUtils,
      ActiveX,
      ComObj;
    
    Const
     XmlStr =
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
    '<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
    '    <Row>'+
    '        <Designation>1234102</Designation>'+
    '        <Inner>5.412</Inner>'+
    '        <Outer>3.588</Outer>'+
    '        <Spin>4.732</Spin>'+
    '        <Cage>0.399</Cage>'+
    '    </Row>'+
    '    <Row>'+
    '        <Designation>1342153</Designation>'+
    '        <Inner>5.916</Inner>'+
    '        <Outer>4.084</Outer>'+
    '        <Spin>5.277</Spin>'+
    '        <Cage>0.408</Cage>'+
    '    </Row>'+
    '</Data>';
    
    procedure Test;
    Var
      XMLDOMDocument  : IXMLDOMDocument;
      XMLDOMNode      : IXMLDOMNode;
    begin
      XMLDOMDocument:=CoDOMDocument.Create;
      XMLDOMDocument.loadXML(XmlStr);
      XMLDOMNode := XMLDOMDocument.selectSingleNode('/Data/Row/Designation[text()="1342153"]');
      if XMLDOMNode<>nil then
       Writeln('Found');
    end;
    
    begin
     try
        CoInitialize(nil);
        try
          Test;
        finally
          CoUninitialize;
        end;
     except
        on E:EOleException do
            Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
        on E:Exception do
            Writeln(E.Classname, ':', E.Message);
     end;
     Writeln('Press Enter to exit');
     Readln;
    end.
    

    【讨论】:

      【解决方案3】:

      在 Delphi 中查询 xml 时,IXMLDocument 和 XPath 是你的朋友 你可以找到很多来源,例如 XPath and TXmlDocument

      【讨论】:

        【解决方案4】:

        由于您想从 xml 查询数据,我建议您使用此处记录的 XML 转换 http://docwiki.embarcadero.com/RADStudio/XE4/en/Converting_XML_Documents_into_Data_Packets

        这会将您的 xml 映射到 ClientDataSet,您可以按您想要的列过滤记录,或者您可以使用 DataBinding 向导,它在此 url http://docwiki.embarcadero.com/RADStudio/XE4/en/Using_the_XML_Data_Binding_Wizard 的文档中有说明

        有关使用 xml 的其他方法,您可以查看文档的主索引这里 http://docwiki.embarcadero.com/RADStudio/XE4/en/Working_with_XML_documents_Index

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多