Как правильно использовать XmlNode.SelectSingleNode (строка xpath) в C #? - PullRequest
18 голосов
/ 08 октября 2011

У меня проблемы с работой с каким-то файлом XML (который находится в конце этого поста).

Я написал следующий код, чтобы получить Job_Id данные, относящиеся к данному шаблону Job_Name, владельцем которого Job_Owner является пользователь, запускающий пробраму:

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.SelectSingleNode("//Job_Name") ищет тег с именем Job_Name только под кодом XML, представленным node.

Это не то, что, кажется, происходит, так как он всегда возвращает один и тот же узел, не имеет значения, на каком шаге foreach он находится (т.е. node, выбранный из nodes, изменяется, но node.SelectSingleNode("//Job_Name") всегда возвращает одно и то же содержимое).

Что не так с этим кодом?

Заранее спасибо!

-

Файл XML выглядит следующим образом:

<Data>
    <Job>
        <Job_Id>58282.minerva</Job_Id>
        <Job_Name>sb_net4_L20_sType1</Job_Name>
        <Job_Owner>mgirardis@minerva</Job_Owner>
        <!--more tags-->
    </Job>
    <Job>
        <!--etc etc etc-->
    </Job>
    <!--etc etc etc-->
</Data>

Ответы [ 4 ]

22 голосов
/ 08 октября 2011

Это потому, что вы используете синтаксис «//» в XPath. Этот специфический синтаксис выбирает первый узел в документе с именем, что. Попробуйте посмотреть https://www.w3schools.com/xml/xpath_syntax.asp информацию о синтаксисе XPath.

Если вы ищете дочерние узлы, попробуйте просто использовать имя узла (IE: «Job_Owner» вместо «// Job_Owner»)

18 голосов
/ 08 октября 2011

Infernex87 правильно, что Job_Owner прост и эффективен для этого случая. Однако, если бы это был не прямой ребенок, вы могли бы сделать:

.//Job_Owner

Как и для каталогов, . является текущим узлом, поэтому он находит потомков текущего узла, а не корня документа.

1 голос
/ 08 октября 2011

Infernex87 прибил причину.Исходя из вашего XML, я думаю, что маршрут LINQ может быть хорошим вариантом для вас.Если вы хотите начать, блог Скотта Гу - отличный ресурс.

0 голосов
/ 02 декабря 2017

мы сделали большую подпрограмму DOM / xML / SQL с помощью скрипта 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]<br>
          // 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);</p>

<code>  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;
</code>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...