首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi7 - OmniXML -选择具有多个参数的特定节点

Delphi7 - OmniXML -选择具有多个参数的特定节点
EN

Stack Overflow用户
提问于 2016-02-02 14:37:13
回答 3查看 454关注 0票数 0

XML文件:

代码语言:javascript
复制
<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中添加多个标准

我的代码:

代码语言:javascript
复制
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;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-03 08:57:45

OmniXMLXPath不支持这一点。然而,我去年增加了对连续过滤器的支持,但忘了将这一更改推到公共站点上:

在更新后的版本中,这将起作用:

代码语言:javascript
复制
program Project29;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  OmniXML,
  OmniXMLXpath,
  OmniXMLUtils;

var
  xml: IXMLDocument;
  node: IXMLNode;

begin
  xml := CreateXMLDoc;
  if XMLLoadFromFile(xml, 'c:\0\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.pashttps://www.dropbox.com/s/nnvrz6wnmnpmxzn/OmniXMLXPath.pas

票数 0
EN

Stack Overflow用户

发布于 2016-02-02 18:21:49

考虑到上面的例子,您可以按照以下几个方面来做一些事情:

代码语言:javascript
复制
//Partner[K2=3]/Invoices/Invoice[R1=1 and R5=398]

这将获得K2=3合作伙伴的Ivoices,其中ivoices具有r1和r5的特定值。然后,根据您需要如何处理符合这些条件的发票(例如,如果有多个发票),您可以使用XPath表达式(如sum或其他什么)返回从这些发票元素中计算出来的单个值。

票数 0
EN

Stack Overflow用户

发布于 2016-02-02 20:07:49

因此,OmniXMLXPath.pas文件OmniXML不支持XPath中的逻辑操作。因此您不能同时使用2+属性进行搜索。

您可以通过调用SelectNodes('//PartnerK3=5254304/Invoices/InvoiceR2='4-02R0113-12')选择多个节点,并通过其他属性检查节点。

如果可以的话,也可以使用MSXML解析器(OmniXML_MSXML单元)。这将适用于您的演示数据:

代码语言:javascript
复制
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;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35156290

复制
相关文章

相似问题

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