问题描述
我正在尝试访问XML文件中的某些节点,但由于我可能不了解Delphi中的XML-Namepsaces,所以无法正常工作.
I am trying to access some Nodes in my XML File, but I cant get it working because i probably don't understand XML-Namepsaces in Delphi.
<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>
我试图这样访问多维数据集节点:
I tried to access the Cube Nodes like that:
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中的名称空间是如何工作的,所以如果我能在这里得到一些帮助,那将是很棒的.
I realized that my output is: "gesmes:Cube".I don't think that is right... I excpected to get the the first "Cube" Node.I am not sure how namespaces in Delphi work so it would be great if i could get some help here.
最好的问候!
推荐答案
您正在将IXMLNode
接口指针传递给ShowMessage()
,该指针需要string
.因此,大概是在您的真实代码中,您实际上已经完成了ShowMessage(Node.ChildNodes['Cube'].NodeName);
.
You are passing an IXMLNode
interface pointer to ShowMessage()
, which expects a string
instead. So presumably, in your real code, you have actually done ShowMessage(Node.ChildNodes['Cube'].NodeName);
instead.
确实报告了'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
.
Which indeed reports 'gesmes:Cube'
, which is not what you are expecting. The Cube
you want is in the http://www.ecb.int/vocabulary/2002-08-01/eurofxref
namespace, which is different than the namespace of its parent Envelope
(http://www.gesmes.org/xml/2002-08-01
). So what actually happens is that DocumentElement.ChildNodes['Cube']
tries to find a Cube
in the Envelope
's namespace, finds no such element, so TXMLDocument
creates a new one because the doNodeAutoCreate
flag is enabled by default in the Doc.Options
property. That is the Cube
that DocumentElement.ChildNodes['Cube']
returns, not the Cube
you want.
由于Envelope
及其直接的Cube
子项位于不同的命名空间中,因此不能在DocumentElement
上使用ChildNodes['Cube']
,而必须使用ChildNodes.FindNode()
,并指定Cube
实际名称空间:
Because the Envelope
and its immediate Cube
child are in different namespaces, you can't use ChildNodes['Cube']
on the DocumentElement
, you have to use ChildNodes.FindNode()
instead, specifying the Cube
's actual namespace:
Node := Doc.DocumentElement;
Node := Node.ChildNodes.FindNode('Cube', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref');
下一个Cube
与它的父级Cube
在相同的名称空间中,因此您可以使用ChildNodes['Cube']
来获取它:
The next Cube
is in the same namespace as its parent Cube
, so you can use ChildNodes['Cube']
to get it:
Node := Node.ChildNodes['Cube'];
然后,如果需要,您可以访问time
属性:
Then you can access the time
attribute, if needed:
Node.Attributes['time']
并遍历其余子Cube
:
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;
这篇关于Delphi中的XML命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!