2011-10-07 46 views
14

いくつかのXMLファイルを扱う際に問題があります(この記事の最後にあります)。C#のXmlNode.SelectSingleNode(string xpath)の正しい使い方は何ですか?

私はその所有者Job_Owner probramを実行しているユーザである与えられたJob_Nameパターンに関連Job_Idデータを取得するために、次のコードを書いた:私はnode.SelectSingleNode("//Job_Name")だけJob_Nameという名前のタグのために求めていることを期待

List<String> jobID = new List<String>(); 
XmlNodeList nodes = xml.SelectNodes("//Job"); 
foreach (XmlNode node in nodes) 
{ 
    innerNode = node.SelectSingleNode("//Job_Owner"); // SelectSingleNode here always selects the same node, but I thought it should be relative to node, not to nodes 
    if (!innerNode.InnerText.Contains(Environment.UserName)) 
    { 
     continue; 
    } 
    innerNode = node.SelectSingleNode("//Job_Name"); 
    if (!Regex.IsMatch(innerNode.InnerText, jobNamePattern, RegexOptions.Compiled)) 
    { 
     continue; 
    } 
    innerNode = node.SelectSingleNode("//Job_Id"); 
    jobID.Add(innerNode.InnerText); 
} 

nodeで表されるxmlコードの下にあります。

それは常に同じノードを返すように、それが起こっているように見えるものではありません、nodes変化から選択nodeすなわち、(それがforeachのどの段階でも問題はなく、node.SelectSingleNode("//Job_Name")は常に返しません同じコンテンツ)。

このコードで何が問題になっていますか?

ありがとうございます!

-

XMLファイルは、次のようになります。あなたは、XPathで '//' 構文を使用しているので、

<Data> 
    <Job> 
     <Job_Id>58282.minerva</Job_Id> 
     <Job_Name>sb_net4_L20_sType1</Job_Name> 
     <Job_Owner>[email protected]</Job_Owner> 
     <!--more tags--> 
    </Job> 
    <Job> 
     <!--etc etc etc--> 
    </Job> 
    <!--etc etc etc--> 
</Data> 
+0

このプログラムが起動している今です! =)〜答えをありがとう! – Girardi

答えて

19

にです。その特定の構文は、その名前のドキュメント内の最初のノードを選択します。 XPathの構文については、https://www.w3schools.com/xml/xpath_syntax.aspを参照してください。

あなたは子ノードを探しているなら、単にノード名(IE:代わりに「// Job_Owner」の「Job_Owner」)を使用してみてください

+2

これはうまくいきました...私はその構文について知っていましたが、 'node'にすべてのドキュメントが含まれていないと、その構文はすべてのドキュメントを検索せず、 'node' – Girardi

+0

Job_Ownerが最初に出現するときに、異なるレベルのJob_Ownerが複数存在する場合に不正確な値を与えるため、//を使用するのに最適な方法ではありません。より良い方法は./Job_Ownerを使用して現在のノードを基準に検索することです。 – evhen14

+0

したがって、/または//を使用してクエリを開始すると、実際にはどのノードでSelectSingleNode()が呼び出されても問題はありません。 –

1

Infernex87は、その理由を釘付けしています。あなたのXMLを見れば、LINQルートはあなたのための良いオプションかもしれないと思います。あなたが始めたいなら、Scott Gu's blogはすばらしい資源です。

+0

はい、LINQ to XMLの検索を少し試してみましたが、まだ実用的なものは何も見つかりませんでした(十分に検索したとは思えません)。ヒントをありがとう! – Girardi

14

このケースでは、Job_Ownerが簡単で効果的なInfernex87は正解です。しかし、それが直接の子でなかった場合、あなたができる:

.//Job_Owner 

をジャストディレクトリのように、.は、現在のノードであるので、これはむしろ、文書のルートよりも、現在のノードの子孫を検索します。

0

我々はmaXboxスクリプトで大きなDOM/XML/SQLルーチンをした:

 
function GetXMLFromURLAdr_IsSame_All(apath: string): boolean; 
    var 
     xml, node: Olevariant; //IXMLDOMDocument; 
     nodes_row, nodes_se, nodex: olevariant; 
     i, j: Integer; 
     sr1,sr2, basenod, basenod2, filePrefix, mySQL, odbcDSN, Auftrag: string; 
    begin 
     xml:= CreateOleObject('Microsoft.XMLDOM') as IXMLDocument; 
     xml.async:= False; 
     if xml.load(apath) then writeln('xml path load success2'); 
     if xml.parseError.errorCode <> 0 then 
     writeln('XML Load error:' + xml.parseError.reason); 
     basenod:= '/WAB/Auftragsliste/Auftrag'; 
     nodes_row:= xml.SelectNodes(basenod); 
     writeln('total auftrag nodes: '+itoa(nodes_row.length)) 
     try 
     for j:= 0 to nodes_row.length-1 do begin 
      //nodes_se:= nodes_row.item[j] 
      node:= nodes_row.item[j]
// writeln(node.text) sr1:= node.selectSingleNode('.//Lieferanschrift/Ort').text sr1:= sr1 + node.selectSingleNode('.//Lieferanschrift/Strasse').text sr2:= node.selectSingleNode('.//Rechnungsanschrift/Ort').text; sr2:= sr2 + node.selectSingleNode('.//Rechnungsanschrift/Strasse').text; writeln(node.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').text); Auftrag:= node.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').text writeln(node.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').text);

if ANSICompareText(sr1, sr2) = 0 then begin srlist:= FindAllFiles(PDFFILEPATH,'*'+Auftrag+'_??.pdf',true); for it:= 0 to srlist.count-1 do begin writeln((srlist.strings[it])); if lCopyFile(srlist.strings[it], PDFEXPORT+extractfilename(srlist.strings[it]),true) then writeln('copyof=: '+srlist.strings[it]); end; srlist.free; srlist:= Nil; it:=0; result:= true; end else begin srlist:= FindAllFiles(PDFFILEPATH,'*'+Auftrag+'*.pdf',true); for it:= 0 to srlist.count-1 do begin if lCopyFile(srlist.strings[it], PDFEXPORT+extractfilename(srlist.strings[it]),true) then writeln('copyof<>: '+srlist.strings[it]); end; DeleteFiles(PDFEXPORT, '*RG.pdf'); DeleteFile(PDFEXPORT+'Special_'+Auftrag+'_ES.pdf'); srlist.free; result:= false end; //mk change in op fileprefix:= 'WAB'; odbcDSN:= 'advance_kmu_loc'; if filePrefix='WAB' then begin mySQL:= 'UPDATE verk_auftrag SET Status = 61 where Auftrag = '+Auftrag; writeln('order back: '+ itoa(MySQLQueryExecute2(mysql, odbcDsn, strtoint(Auftrag),true))); end; if filePrefix='WEA' then begin mySQL:= 'UPDATE verk_auftrag SET Status = 52 where Auftrag = '+Auftrag; writeln('order back: '+ itoa(MySQLQueryExecute2(mysql, odbcDsn, strtoint(Auftrag),true))); end; } nodes_se:= node.selectNodes('.//Auftragspositionen/Position'); writeln('total posnod: '+itoa(nodes_se.length)) for i:= 0 to nodes_se.length - 1 do begin node:= nodes_se.item[i]; writeln('Posit=' + node.text); end;//} writeln('------------------------'); end; //} except writeln(exceptiontoString(exceptiontype, exceptionparam)) finally xml:= unassigned; xml:= NULL; end; end;

+0

こんにちはマックス、あなたはこのコードがOPのコードはしていないことについていくつかの有用なヒントを提供できますか?これはなぜ正しいのですか、そのコードはなぜですか?どのように動作するの違いは何ですか?前もって感謝します。 –

+0

コードはXMLベースのデータセットパケット(クライアントデータセット)から日付を解析し、いくつかのpdfファイルをコピーし、それに基づいて別のデータセットを更新します。 両方のコードが正しいです。 –

関連する問題