2011-10-07 27 views
14

Tengo problemas para tratar con algún archivo XML (que se encuentra al final de esta publicación).¿Cuál es el uso correcto de XmlNode.SelectSingleNode (string xpath) en C#?

me escribió el siguiente código a fin de obtener Job_Id datos relacionados con un Job_Name patrón determinado cuyo propietario Job_Owner es el usuario que ejecuta el 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); 
} 

yo esperaría que node.SelectSingleNode("//Job_Name") busca de una etiqueta llamada Job_Name solamente bajo el código xml representado por node.

Eso no es lo que parece estar sucediendo, ya que siempre devuelven el mismo nodo, no importa en qué paso del foreach es (es decir, el node seleccionado de los nodes cambios, pero el node.SelectSingleNode("//Job_Name") siempre devuelven el mismo contenido).

¿Qué hay de malo en este código?

¡Gracias de antemano!

-

el archivo XML tiene el siguiente aspecto:

<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

Este programa ya está en marcha y funcionando! =) ~ ¡Gracias por las respuestas! – Girardi

Respuesta

19

Es porque usted está utilizando la sintaxis '//' en el XPath. Esa sintaxis específica selecciona el primer nodo en el documento llamado así. Intente mirar https://www.w3schools.com/xml/xpath_syntax.asp para obtener información sobre la sintaxis de XPath.

Si usted está buscando nodos secundarios, intente simplemente usando el nombre de nodo (IE: 'Job_Owner' en lugar de '// Job_Owner')

+2

Bueno, eso funciona ... Sabía de esa sintaxis, pero parecía razonable que si 'node' no contiene todo el documento, entonces esa sintaxis no buscaría todo el documento, sino que buscaría solo dentro del código representado por 'node' – Girardi

+0

No es el mejor enfoque para usar //, ya que dará valores incorrectos en los casos en que haya varios Job_Owner en diferentes niveles, ya que devuelve la primera aparición de cualquier Job_Owner. Mejor manera es usar ./Job_Owner ya que buscará en relación con el nodo actual. – evhen14

+0

Entonces, ¿el punto es que si comienzas la consulta con/o //, en realidad no importa en qué nodo estás llamando 'SelectSingleNode()' activado? –

1

Infernex87 ha clavado el motivo. Pasando por su XML, supongo que ir por la ruta LINQ podría ser una buena opción para usted. Si desea comenzar, Scott Gu's blog es un gran recurso.

+0

Sí, traté de buscar un poco de LINQ en XML, pero no pude encontrar nada pragmático (¡aunque no creo que haya buscado lo suficiente!). ¡Gracias por el consejo! – Girardi

14

Infernex87 es correcto que Job_Owner es simple y efectivo para este caso. Sin embargo, si no fuera un niño directa, que podría hacer:

.//Job_Owner 

Al igual que para los directorios, . es el nodo actual, por lo que este se encuentra descendientes del nodo actual, en lugar de la raíz del documento.

0

hemos hecho un gran DOM rutina/XML/SQL con la escritura 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

Hola Max, ¿puedes proporcionar algunos consejos útiles sobre qué está haciendo este código que el código del OP no ofrece? ¿Por qué es esto correcto y su código no? ¿Cuál es la diferencia en cómo funciona? Gracias por adelantado. –

+0

el código analiza alguna fecha de un paquete de conjunto de datos basado en XML (conjunto de datos de cliente), copia unos pocos archivos pdf y en función de eso actualiza otro conjunto de datos. Ambos códigos son correctos. –

Cuestiones relacionadas