0

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>ます。各パートナーには、 node に書き込まれた独自の識別番号があります<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;
4

3 に答える 3

0

OmniXMLXPath はそのままではサポートしていません。ただし、昨年連続フィルターのサポートを追加しましたが、その変更を公開サイトにプッシュするのを忘れていました:(

更新されたバージョンでは、これは機能します:

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.pasます: https://www.dropbox.com/s/nnvrz6wnmnpmxzn/OmniXMLXPath.pas

于 2016-02-03T08:57:45.350 に答える
0

上記の例を考えると、次の行に沿って何かを行うことができます。

//Partner[K2=3]/Invoices/Invoice[R1=1 and R5=398]

これは、ivoice が r1 と r5 に特定の値を持つ、K2=3 のパートナーの Ivoices を取得します。次に、これらの条件に一致する請求書をどのように処理する必要があるかに応じて (複数の請求書がある場合など)、XPath 式 (合計など) を使用して、これらの Invoice 要素から計算された単一の値を返すことができます。

于 2016-02-02T18:21:49.863 に答える
0

したがって、OmniXMLXPath.pas ファイルでは、OmniXML は XPath での論理演算をサポートしていません。したがって、2 つ以上の属性で同時に検索することはできません。

SelectNodes('//Partner[K3=5254304]/Invoices/Invoice[R2='4-02R0113-12'])を呼び出して複数のノードを選択し、別の属性でノードを確認できます。

または、可能であれば 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;
于 2016-02-02T20:07:49.010 に答える