Che cosa è l’uso corretto di XmlNode.SelectSingleNode(string xpath) in C#?

Sto avendo problemi con alcuni file XML (che è alla fine di questo post).

Ho scritto il seguente codice per ottenere Job_Id dati relativi a un determinato Job_Name modello il cui proprietario Job_Owner è l’utente che esegue il 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);
}

Mi aspetterei che node.SelectSingleNode("//Job_Name") cerca un tag chiamato Job_Name solo sotto il codice xml rappresentato da node.

Che non è quello che sembra stia accadendo, come si restituiscono sempre lo stesso nodo, non importa in quale punto dell’ foreach è (cioè il node selezionati dal nodes cambia, ma la node.SelectSingleNode("//Job_Name") restituiscono sempre lo stesso contenuto).

Cosa c’è di sbagliato con questo codice?

Grazie in anticipo!

Il File XML simile a questo:

<Data>
    <Job>
        <Job_Id>58282.minerva</Job_Id>
        <Job_Name>sb_net4_L20_sType1</Job_Name>
        <Job_Owner>mgirardis[email protected]</Job_Owner>
        <!--more tags-->
    </Job>
    <Job>
        <!--etc etc etc-->
    </Job>
    <!--etc etc etc-->
</Data>
InformationsquelleAutor Girardi | 2011-10-07

 

4 Replies
  1. 22

    È perché stai usando il ‘//’ la sintassi XPath. Che sintassi specifica seleziona il primo nodo del documento denominato che. Prova a guardare https://www.w3schools.com/xml/xpath_syntax.asp per informazioni sulla sintassi XPath.

    Se siete alla ricerca per i nodi figlio, provare utilizzando il nome del nodo (IE: ‘Job_Owner’ invece di ‘//Job_Owner’)

    • Beh, che funziona… ho saputo che la sintassi, ma sembrava ragionevole che se node non contiene tutti i documenti, quindi, che la sintassi non ricerca tutti i documenti, ma di cercare solo all’interno del codice rappresentato da node
    • Non è l’approccio migliore da utilizzare // come sarà dare valori non corretti nei casi in cui ci sono più Job_Owner su diversi livelli, come ritorna la prima occorrenza di qualsiasi Job_Owner. Il modo migliore è quello di utilizzare ./Job_Owner come ricerca relativa al nodo corrente.
    • Quindi il punto è che se si avvia la query con / o //, in realtà, non importa che cosa il nodo che si sta chiamando SelectSingleNode() su?
    • In realtà stavo solo leggendo quel w3schools pagina. Mentre si insegna a forma di una query XPath, non risolve la questione, perché non parlare utilizzando le query come argomenti per i metodi come SelectSingleNode() che sono chiamati a specifici oggetti di un nodo.
  2. 18

    Infernex87 è corretto che Job_Owner è semplice ed efficace per questo caso. Tuttavia, se si trattasse di un bambino, si potrebbe fare:

    .//Job_Owner

    Proprio come per le directory, . è il nodo corrente, in modo che questo trova discendenti del nodo corrente, piuttosto che la radice del documento.

    • Penso che dovrebbe essere esplicitamente detto (non solo implicita), che i metodi SelectNodes() e SelectSingleNode() hanno accesso all’intero documento XML e richiedono l’ancoraggio con “./” a funzionare come previsto. Utilizzare “./Job_Owner” root al contesto attuale posizione.
  3. 1

    Infernex87 ha inchiodato il motivo. Andando da XML, credo che andando LINQ percorso può essere una buona opzione per voi. Se si desidera avviare, Scott Gu blog è una grande risorsa.

    • Sì, ho provato a cercare un po ‘ di LINQ to XML, ma non riuscivo a trovare nulla di pragmatico fuori c’è ancora (anche se non credo che ho cercato abbastanza!). Grazie per il suggerimento!
  4. 0

    abbiamo fatto un grande DOM /xML /SQL Routine con maXbox script:

    funzione GetXMLFromURLAdr_IsSame_All(apath: string): boolean; 
    var. 
    xml, nodo: 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') come IXMLDocument; 
    xml.async:= False; 
    se xml.carica(apath) quindi writeln( "xml percorso di carico success2'); 
    se xml.parseError.errorCode <> 0 quindi 
    writeln( " XML Carico di errore:' + xml.parseError.la ragione); 
    basenod:= '/RUBRICA/Auftragsliste/Auftrag'; 
    nodes_row:= xml.SelectNodes(basenod); 
    writeln('totale auftrag nodi: '+itoa(nodes_row.lunghezza)) 
    prova 
    per j:= 0 per nodes_row.lunghezza-1 do begin 
    //nodes_se:= nodes_row.elemento a[j] 
    nodo:= nodes_row.articolo[j]
    //writeln(nodo.il testo) sr1:= nodo.selectSingleNode('.//Lieferanschrift/Ort').testo sr1:= 1 + nodo.selectSingleNode('.//Lieferanschrift/Strasse').testo sr2:= nodo.selectSingleNode('.//Rechnungsanschrift/Ort').testo; sr2:= sr2 + nodo.selectSingleNode('.//Rechnungsanschrift/Strasse').testo; writeln(nodo.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').testo); Auftrag:= nodo.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').testo writeln(nodo.selectSingleNode('.//Auftragskopf/FremdlieferscheinNr').testo);

    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;

    • Ciao Max, si può fornire alcuni utili consigli su cosa questo codice fa che l’OP del codice non? Perché questo è corretto, e il loro codice non lo è? Qual è la differenza in come funziona? Grazie in anticipo.
    • il codice analizza alcuni data basata su XML dataset pacchetto (client set di dati), copiare alcuni files pdf e, su tale base gli aggiornamenti di un altro set di dati. Entrambi i codici sono corretti.

Lascia un commento