2011-10-07 47 views
14

Tôi đang gặp sự cố khi xử lý một số tệp XML (ở cuối bài đăng này).Việc sử dụng chính xác của XmlNode.SelectSingleNode (xpath chuỗi) trong C# là gì?

tôi đã viết đoạn mã sau để có được Job_Id dữ liệu liên quan đến một Job_Name mẫu cho mà chủ sở hữu Job_Owner là người sử dụng chạy các probram:

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); 
} 

Tôi mong rằng node.SelectSingleNode("//Job_Name") tìm kiếm cho một từ khóa duy nhất tên là Job_Name theo mã xml được biểu thị bởi node.

Đó không phải là những gì nó có vẻ thể xảy ra, vì nó luôn luôn quay trở lại cùng một nút, không quan trọng vào những gì bước của foreach nó là (tức là node chọn từ nodes thay đổi, nhưng node.SelectSingleNode("//Job_Name") luôn trả lại cùng một nội dung).

Điều gì sai với mã này?

Cảm ơn trước!

-

XML file trông như thế này:

<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

chương trình này bây giờ là dậy và chạy! =) ~ Cảm ơn câu trả lời! – Girardi

Trả lời

19

Đó là bởi vì bạn đang sử dụng cú pháp '//' trong XPath. Cú pháp cụ thể đó chọn nút đầu tiên trong tài liệu có tên đó. Hãy thử xem https://www.w3schools.com/xml/xpath_syntax.asp để biết thông tin về cú pháp XPath.

Nếu bạn đang tìm kiếm các nút con, hãy thử chỉ sử dụng tên nút (IE: 'Job_Owner' thay vì '// Job_Owner')

+2

Vâng, nó hoạt động ... Tôi biết về cú pháp đó nhưng nó có vẻ hợp lý nếu 'node' không chứa tất cả tài liệu, thì cú pháp đó sẽ không tìm kiếm tất cả tài liệu, nhưng chỉ tìm kiếm bên trong mã được biểu diễn bởi 'node' – Girardi

+0

Không phải cách tiếp cận tốt nhất để sử dụng // vì nó sẽ cung cấp các giá trị không chính xác trong trường hợp có nhiều Job_Owner ở các mức khác nhau khi nó trả về lần xuất hiện đầu tiên của bất kỳ Job_Owner nào. Cách tốt hơn là sử dụng ./Job_Owner vì nó sẽ tìm kiếm tương đối so với nút hiện tại. – evhen14

+0

Vì vậy, vấn đề là nếu bạn bắt đầu truy vấn với/hoặc //, nó thực sự không quan trọng nút bạn đang gọi 'SelectSingleNode()' trên? –

1

Infernex87 đã đóng đinh lý do. Đi theo XML của bạn, tôi đoán đi tuyến đường LINQ có thể là một lựa chọn tốt cho bạn. Nếu bạn muốn bắt đầu, Scott Gu's blog là một nguồn tài nguyên tuyệt vời.

+0

Có, tôi đã thử tìm kiếm một chút LINQ to XML, nhưng tôi không thể tìm thấy bất kỳ điều gì thực dụng ngoài đó (độ cao tôi không nghĩ rằng tôi đã tìm kiếm đủ!). Cảm ơn vì tiền hỗ trợ! – Girardi

14

Infernex87 đúng là Job_Owner rất đơn giản và hiệu quả cho trường hợp này. Tuy nhiên, nếu nó không phải là một đứa trẻ trực tiếp, bạn có thể làm:

.//Job_Owner 

Cũng giống như đối với thư mục, . là nút hiện hành, vì vậy đây tìm thấy hậu duệ của nút hiện tại, chứ không phải là thư mục gốc của tài liệu.

0

chúng tôi đã làm một DOM/xml/SQL Routine lớn với maXbox kịch bản:

 
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

Xin chào Max, bạn có thể cung cấp một số lời khuyên hữu ích về những gì mã này đang làm mà mã của OP không? Tại sao điều này đúng và mã của họ không đúng? Sự khác biệt trong cách thức hoạt động của nó là gì? Cảm ơn trước. –

+0

mã phân tích một số ngày từ gói dữ liệu dựa trên XML (bộ dữ liệu khách hàng), sao chép một vài tệp pdf và dựa trên đó cập nhật tập dữ liệu khác. Cả hai mã đều chính xác. –

Các vấn đề liên quan