2011-10-07 8 views
14

Mam problem z zajęciem się jakimś plikiem XML (który znajduje się na końcu tego posta).Jakie jest prawidłowe użycie XmlNode.SelectSingleNode (ciąg xpath) w języku C#?

Napisałem następujący kod w celu uzyskania Job_Id danych związanych z danym Job_Name wzór, którego właściciel Job_Owner jest użytkownik uruchamiający 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); 
} 

Spodziewam się, że node.SelectSingleNode("//Job_Name") poszukuje dla tagu nazwie Job_Name tylko pod kodem xml reprezentowanym przez node.

To nie jest to, co wydaje się dziać, ponieważ zawsze zwraca ten sam węzeł, nie ma znaczenia, na jakim etapie foreach to jest (czyli node wybrane spośród nodes zmian, ale zawsze zwracają node.SelectSingleNode("//Job_Name") ta sama treść).

Co jest nie tak z tym kodem?

Z góry dziękuję!

-

pliku XML wygląda następująco:

<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

Ten program jest teraz gotowy do pracy! =) ~ Dzięki za odpowiedzi! – Girardi

Odpowiedz

19

To dlatego, że używasz '//' w składni XPath. Ta specyficzna składnia wybiera pierwszy węzeł w dokumencie o nazwie. Spróbuj przejrzeć https://www.w3schools.com/xml/xpath_syntax.asp, aby uzyskać informacje na temat składni XPath.

Jeśli szukasz węzłów potomnych, spróbuj tylko przy użyciu nazwy węzła (czyli: „Job_Owner” zamiast „// Job_Owner”)

+2

Cóż, to działa ... Wiedziałem o tej składni, ale brzmiało rozsądnie, że jeśli 'węzeł' nie zawiera całego dokumentu, to ta składnia nie przeszukałaby całego dokumentu, ale wyszukałaaby tylko wewnątrz kodu reprezentowanego przez 'węzeł' – Girardi

+0

Nie jest to najlepsze podejście do użycia //, ponieważ daje niepoprawne wartości w przypadkach, gdy istnieje wiele Job_Owner na różnych poziomach, ponieważ zwraca pierwsze wystąpienie Job_Owner. Lepszym sposobem jest użycie ./Job_Owner, ponieważ będzie wyszukiwać względem bieżącego węzła. – evhen14

+0

Tak więc chodzi o to, że jeśli uruchomisz zapytanie z/lub //, nie ma to znaczenia, do którego węzła wywołujesz 'SelectSingleNode()' na? –

1

Infernex87 został przybity przyczyny. Przechodząc przez XML, domyślam się, że wybór trasy LINQ może być dla ciebie dobrym rozwiązaniem. Jeśli chcesz zacząć, Scott Gu's blog to świetny zasób.

+0

Tak, próbowałem wyszukać trochę LINQ w XML, ale nie mogłem znaleźć niczego pragmatycznego (choć nie sądzę, że przeszukałem wystarczająco!). Dzięki za wskazówkę! – Girardi

14

Infernex87 jest poprawny, ponieważ Job_Owner jest prosty i skuteczny w tym przypadku. Jednak gdyby nie było bezpośrednim dzieckiem, można zrobić:

.//Job_Owner 

podobnie jak dla katalogów, . jest obecny węzeł, więc ta znajdzie potomków bieżącego węzła, zamiast korzenia dokumentu.

0

zrobiliśmy duży DOM/XML/SQL rutynowe z skryptu maXbox:

 
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

Witam Max, czy możesz podać kilka przydatnych wskazówek na temat tego, co robi ten kod, czego nie zawiera kod PO? Dlaczego jest to poprawne, a ich kod nie jest? Jaka jest różnica w działaniu? Z góry dziękuję. –

+0

kod analizuje niektóre daty z pakietu danych bazującego na XML (zestaw danych klienta), kopiuje kilka plików pdf i na tej podstawie aktualizuje inny zestaw danych. Oba kody są prawidłowe. –

Powiązane problemy