Delphi7 - OmniXML - select 具有多个参数的特定节点
Delphi7 - OmniXML - select specific node with multiple parameters
XML 文件:
<Partner>
...
</Partner>
<Partner>
<K1>10</K1>
<K2>3</K2>
<K3>5254304</K3>
<K4>test name</K4>
<K5>637.51</K5>
<K6>159.38</K6>
<K7>802.39</K7>
<K8>0.00</K8>
<K9>802.39</K9>
<Invoices>
<Invoice>
<R1>1</R1>
<R2>4-02R0113-12</R2>
<R3>2014-12-29</R3>
<R4>2014-12-29</R4>
<R5>398</R5>
<R6>637.51</R6>
<R7>159.38</R7>
<R8>802.39</R8>
<R9>0.00</R9>
<R10>802.39</R10>
</Invoice>
</Invoices>
</Partner>
<Partner>
...
</Partner>
在我的 XML 文件中,我有重复节点 <Partner>
。每个合作伙伴都有自己的标识号,写在节点 <K3>
.
中
每个合作伙伴可以有多张发票。
我需要在发票中的 <R6>
和 <R7>
中查找并读取值
我知道 <R2>
、<R3>
、<R8>
.
的值
如何搜索合作伙伴的多个字段 <R2>
、<R3>
、<R8>
的特定发票,其中搜索条件是字段 <K3>
并获取字段<R6>
和 <R7>
?
的值
如何向 SelectSingleNode
添加多个条件?
我的代码:
procedure TfrmTest.TestReadOmniXML;
var
xml: IXMLDocument;
iNodePartner, iNodePartnerInvoice, iNodePartnerInvoiceR6, iNodePartnerInvoiceR7 : IXMLNode;
begin
xml := CreateXMLDoc;
xml.Load('c:\test.xml');
iNodePartner := XML.SelectSingleNode('//Partner[K3=' + '0254304' + ']');
iNodePartnerInvoice := iNodePartner.SelectSingleNode(
//single query works OK
'.//Racuni/Racun[R2=' + '4-02R0113-12' + ']'
//but I need to add these fields also
// ' and [R3=' + '2014-12-29' + ']' +
// ' and [R8=' + '802.39' + ']'
);
if Assigned( iNodePartnerInvoice ) then
begin
iNodePartnerInvoiceR6 := iNodePartnerInvoice.SelectSingleNode('./R6');
Label1.Caption := iNodePartnerInvoiceR6.Text;
iNodePartnerInvoiceR7 := iNodePartnerInvoice.SelectSingleNode('./R7');
Label2.Caption := iNodePartnerInvoiceR7.Text;
end;
...
end;
鉴于上面的示例,您可以按照以下方式执行操作:
//Partner[K2=3]/Invoices/Invoice[R1=1 and R5=398]
这会获取 K2=3 的合作伙伴的象牙,其中象牙具有特定的 r1 和 r5 值。然后,根据您需要如何处理符合这些条件的发票(例如,如果有多个发票),您可以使用 XPath 表达式(如 sum 或其他东西)来 return 计算出的单个值这些发票元素。
根据OmniXMLXPath.pas文件,OmniXML不支持XPath中的逻辑运算。所以你不能同时搜索 2+ 个属性。
您可以通过调用 SelectNodes('//Partner[K3=5254304]/Invoices/Invoice[R2='4-02R0113-12'])[来 select 多个节点 并通过另一个属性检查节点。
或者如果可以的话使用 MSXML 解析器(OmniXML_MSXML 单元)。这将适用于您的演示数据:
procedure TForm1.Button1Click(Sender: TObject);
var
xml: IXMLDocument;
iNodePartner: IXMLNode;
begin
xml := CreateXMLDoc;
xml.Load('c:\test.xml');
iNodePartner := XML.selectSingleNode('//Partner[K3=5254304]/Invoices/Invoice[R2=''4-02R0113-12'' and R8=''802.39'']');
if iNodePartner = nil then
MessageDlg('Not found',mterror,[mbok],0);
end;
OmniXMLXPath 不支持开箱即用。但是,我去年添加了对连续过滤器的支持,但忘记将更改推送到 public 站点 :(
对于更新版本,这将起作用:
program Project29;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
OmniXML,
OmniXMLXpath,
OmniXMLUtils;
var
xml: IXMLDocument;
node: IXMLNode;
begin
xml := CreateXMLDoc;
if XMLLoadFromFile(xml, 'c:[=10=]\partner.xml') then begin
node := xml.SelectSingleNode('//Partner/Invoices/Invoice[R2="4-02R0113-12"][R3="2014-12-29"][R8="802.39"]');
if not assigned(node) then
Writeln('not found')
else begin
Writeln('R6=', GetNodeTextStr(node, 'R6', ''));
Writeln('R7=', GetNodeTextStr(node, 'R7', ''));
end;
end;
Readln;
end.
现在,您可以在这里获得新鲜的 OmniXMLXPath.pas
:https://www.dropbox.com/s/nnvrz6wnmnpmxzn/OmniXMLXPath.pas
XML 文件:
<Partner>
...
</Partner>
<Partner>
<K1>10</K1>
<K2>3</K2>
<K3>5254304</K3>
<K4>test name</K4>
<K5>637.51</K5>
<K6>159.38</K6>
<K7>802.39</K7>
<K8>0.00</K8>
<K9>802.39</K9>
<Invoices>
<Invoice>
<R1>1</R1>
<R2>4-02R0113-12</R2>
<R3>2014-12-29</R3>
<R4>2014-12-29</R4>
<R5>398</R5>
<R6>637.51</R6>
<R7>159.38</R7>
<R8>802.39</R8>
<R9>0.00</R9>
<R10>802.39</R10>
</Invoice>
</Invoices>
</Partner>
<Partner>
...
</Partner>
在我的 XML 文件中,我有重复节点 <Partner>
。每个合作伙伴都有自己的标识号,写在节点 <K3>
.
每个合作伙伴可以有多张发票。
我需要在发票中的 <R6>
和 <R7>
中查找并读取值
我知道 <R2>
、<R3>
、<R8>
.
如何搜索合作伙伴的多个字段 <R2>
、<R3>
、<R8>
的特定发票,其中搜索条件是字段 <K3>
并获取字段<R6>
和 <R7>
?
如何向 SelectSingleNode
添加多个条件?
我的代码:
procedure TfrmTest.TestReadOmniXML;
var
xml: IXMLDocument;
iNodePartner, iNodePartnerInvoice, iNodePartnerInvoiceR6, iNodePartnerInvoiceR7 : IXMLNode;
begin
xml := CreateXMLDoc;
xml.Load('c:\test.xml');
iNodePartner := XML.SelectSingleNode('//Partner[K3=' + '0254304' + ']');
iNodePartnerInvoice := iNodePartner.SelectSingleNode(
//single query works OK
'.//Racuni/Racun[R2=' + '4-02R0113-12' + ']'
//but I need to add these fields also
// ' and [R3=' + '2014-12-29' + ']' +
// ' and [R8=' + '802.39' + ']'
);
if Assigned( iNodePartnerInvoice ) then
begin
iNodePartnerInvoiceR6 := iNodePartnerInvoice.SelectSingleNode('./R6');
Label1.Caption := iNodePartnerInvoiceR6.Text;
iNodePartnerInvoiceR7 := iNodePartnerInvoice.SelectSingleNode('./R7');
Label2.Caption := iNodePartnerInvoiceR7.Text;
end;
...
end;
鉴于上面的示例,您可以按照以下方式执行操作:
//Partner[K2=3]/Invoices/Invoice[R1=1 and R5=398]
这会获取 K2=3 的合作伙伴的象牙,其中象牙具有特定的 r1 和 r5 值。然后,根据您需要如何处理符合这些条件的发票(例如,如果有多个发票),您可以使用 XPath 表达式(如 sum 或其他东西)来 return 计算出的单个值这些发票元素。
根据OmniXMLXPath.pas文件,OmniXML不支持XPath中的逻辑运算。所以你不能同时搜索 2+ 个属性。
您可以通过调用 SelectNodes('//Partner[K3=5254304]/Invoices/Invoice[R2='4-02R0113-12'])[来 select 多个节点 并通过另一个属性检查节点。
或者如果可以的话使用 MSXML 解析器(OmniXML_MSXML 单元)。这将适用于您的演示数据:
procedure TForm1.Button1Click(Sender: TObject);
var
xml: IXMLDocument;
iNodePartner: IXMLNode;
begin
xml := CreateXMLDoc;
xml.Load('c:\test.xml');
iNodePartner := XML.selectSingleNode('//Partner[K3=5254304]/Invoices/Invoice[R2=''4-02R0113-12'' and R8=''802.39'']');
if iNodePartner = nil then
MessageDlg('Not found',mterror,[mbok],0);
end;
OmniXMLXPath 不支持开箱即用。但是,我去年添加了对连续过滤器的支持,但忘记将更改推送到 public 站点 :(
对于更新版本,这将起作用:
program Project29;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
OmniXML,
OmniXMLXpath,
OmniXMLUtils;
var
xml: IXMLDocument;
node: IXMLNode;
begin
xml := CreateXMLDoc;
if XMLLoadFromFile(xml, 'c:[=10=]\partner.xml') then begin
node := xml.SelectSingleNode('//Partner/Invoices/Invoice[R2="4-02R0113-12"][R3="2014-12-29"][R8="802.39"]');
if not assigned(node) then
Writeln('not found')
else begin
Writeln('R6=', GetNodeTextStr(node, 'R6', ''));
Writeln('R7=', GetNodeTextStr(node, 'R7', ''));
end;
end;
Readln;
end.
现在,您可以在这里获得新鲜的 OmniXMLXPath.pas
:https://www.dropbox.com/s/nnvrz6wnmnpmxzn/OmniXMLXPath.pas