【问题标题】:XML Namespace in DelphiDelphi 中的 XML 命名空间
【发布时间】:2018-01-19 14:19:21
【问题描述】:

我正在尝试访问我的 XML 文件中的一些节点,但我无法让它工作,因为我可能不了解 Delphi 中的 XML-Namepsaces。

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2018-01-18">
            <Cube currency="USD" rate="1.2235"/>
            <Cube currency="JPY" rate="136.07"/>
            <Cube currency="BGN" rate="1.9558"/>
            <Cube currency="CZK" rate="25.365"/>
            <Cube currency="DKK" rate="7.4475"/>
            <Cube currency="GBP" rate="0.88208"/>
            <Cube currency="HUF" rate="308.51"/>
            <Cube currency="PLN" rate="4.1665"/>
            <Cube currency="RON" rate="4.6480"/>
            <Cube currency="SEK" rate="9.8305"/>
            <Cube currency="CHF" rate="1.1748"/>
            <Cube currency="NOK" rate="9.6013"/>
            <Cube currency="HRK" rate="7.4409"/>
            <Cube currency="RUB" rate="69.2126"/>
            <Cube currency="TRY" rate="4.6374"/>
            <Cube currency="AUD" rate="1.5311"/>
            <Cube currency="BRL" rate="3.9321"/>
            <Cube currency="CAD" rate="1.5229"/>
            <Cube currency="CNY" rate="7.8582"/>
            <Cube currency="HKD" rate="9.5648"/>
            <Cube currency="IDR" rate="16325.38"/>
            <Cube currency="ILS" rate="4.1950"/>
            <Cube currency="INR" rate="78.1210"/>
            <Cube currency="KRW" rate="1306.61"/>
            <Cube currency="MXN" rate="22.8174"/>
            <Cube currency="MYR" rate="4.8396"/>
            <Cube currency="NZD" rate="1.6759"/>
            <Cube currency="PHP" rate="62.068"/>
            <Cube currency="SGD" rate="1.6175"/>
            <Cube currency="THB" rate="39.054"/>
            <Cube currency="ZAR" rate="15.0035"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

我尝试这样访问多维数据集节点:

procedure TForm2.Button1Click(Sender: TObject);
var
  Doc: IXMLDocument;
  Node: IXMLNode;
  sl: TStringList;
begin
  Doc := LoadXMLDocument('C:\Users\Kevin\Desktop\test.xml');
  node := Doc.DocumentElement;

  ShowMessage(Node.ChildNodes['Cube']);
end;

我意识到我的输出是:“gesmes:Cube”。 我不认为这是正确的......我期望得到第一个“立方体”节点。 我不确定 Delphi 中的命名空间是如何工作的,所以如果我能在这里得到一些帮助会很棒。

最好的问候!

【问题讨论】:

    标签: xml delphi namespaces


    【解决方案1】:

    您将一个IXMLNode 接口指针传递给ShowMessage(),它需要一个string。所以推测,在你的真实代码中,你实际上已经完成了ShowMessage(Node.ChildNodes['Cube'].NodeName);

    确实报告了'gesmes:Cube',这不是您所期望的。您想要的 Cube 位于 http://www.ecb.int/vocabulary/2002-08-01/eurofxref 命名空间中,该命名空间不同于其父 Envelope (http://www.gesmes.org/xml/2002-08-01) 的命名空间。所以实际发生的是DocumentElement.ChildNodes['Cube'] 试图在Envelope 的命名空间中找到Cube,但没有找到这样的元素,所以TXMLDocument 创建一个新的 因为doNodeAutoCreate默认情况下,Doc.Options 属性中启用标志。那是DocumentElement.ChildNodes['Cube'] 返回的Cube,而不是你想要的Cube

    因为Envelope 和它的直接Cube 子在不同的命名空间中,你不能在DocumentElement 上使用ChildNodes['Cube'],你必须使用ChildNodes.FindNode(),指定Cube's实际命名空间:

    Node := Doc.DocumentElement;
    Node := Node.ChildNodes.FindNode('Cube', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref');
    

    下一个Cube与其父Cube在同一个命名空间中,所以你可以使用ChildNodes['Cube']来获取它:

    Node := Node.ChildNodes['Cube'];
    

    如果需要,您可以访问time 属性:

    Node.Attributes['time']
    

    并循环遍历剩余的孩子Cubes:

    Node := Node.ChildNodes.First;
    while Node <> nil do
    begin
      if Node.LocalName = 'Cube' then
      begin
        // use Node.Attributes['currency'] and Node.Attributes['rate'] as needed...
      end;
      Node := Node.NextSibling;
    end;
    

    完整代码如下:

    procedure TForm2.Button1Click(Sender: TObject);
    var
      Doc: IXMLDocument;
      Node: IXMLNode;
      sl: TStringList;
    begin
      sl := TStringList.Create;
      try
        Doc := LoadXMLDocument('C:\Users\Kevin\Desktop\test.xml');
        try
          Node := Doc.DocumentElement;
          if Node = nil then ... // handle the error as needed...
    
          Node := Node.ChildNodes.FindNode('Cube', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref');
          if Node = nil then ... // handle the error as needed...
    
          Node := Node.ChildNodes['Cube'];
          if Node = nil then ... // handle the error as needed...
    
          Node := Node.ChildNodes.First;
          while Node <> nil do
          begin
            if Node.LocalName = 'Cube' then
              sl.Add(Node.Attributes['currency'] + '=' + Node.Attributes['rate']);
            Node := Node.NextSibling;
          end;
        finally
          Node := nil;
          Doc := nil;
        end;
    
        // use sl as needed...
    
      finally
        sl.Free;
      end;
    end;
    

    【讨论】:

    • 非常感谢,这很有帮助。即使现在有点晚了。该项目暂停了一段时间
    猜你喜欢
    • 2011-01-07
    • 1970-01-01
    • 2017-08-14
    • 2014-05-26
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多