2014-01-17 2 views
0

У меня есть файл XML в следующем форматеЗапросы к XML и обновление некоторых элементов

<?xml version="1.0" ?> 
<AA someattrib="xyz"> 
    <BB someOtherAttrib="xyz"> 
    <Title></Title> 
     <CC> 

      <myNode rowid=""> 
       <subNode1></subNode1> 
       <subNode2></subNode2> 
       <nodeOfInterest></nodeOfInterest> 
      </myNode > 
      <myNode rowid=""> 
       <subNode1> </subNode1> 

      </myNode> 
     </CC> 
    </BB> 
</AA> 

Я хочу использовать Linq, чтобы выбрать один узел под названием «MyNode» где ROWID является конкретным числом, что я будет получать из коллекции в объекте. Когда я получу myNode, я хочу обновить значение дочернего узлаOfInterest, если он присутствует. Если нет, то я хотел бы добавить его. После этого я хочу сохранить файл.

Это то, что у меня есть на данный момент, но это может быть неправильный подход.

foreach (User employee in Users) 
    { 

     XPathNavigator node = xNav.SelectSingleNode("/AA/BB/CC/myNode[@rowid = '"+employee.ID.ToString()+"']"); 
     XPathNodeIterator nodeIterator= node.SelectChildren("nodeOfInterest", ""); 
     if (nodeIterator.Count == 1) 
     { 

     } 
     else 
     { 
     } 

    } 

Есть ли способ, которым это можно сделать, используя прямое соединение между списком и xmldoc в памяти? Это будет большой список и одинаково большой xml-файл. Я не думаю, что запуск цикла и вызов selectSingleNode является наиболее эффективным способом.

Спасибо за ваши входы

ответ

0

Полный ответ, с помощью ответов Йона ...

var doc = XDocument.Load("thefile.xml"); 
var dictionary = doc.Element("AA").Element("BB").Element("CC").Elements("myNode") 
       .ToDictionary(x => x.Attribute("rowId").Value); 

foreach (User employee in Users) 
{ 
    XElement myNode; 
    if (dictionary.TryGetValue(employee.ID, out myNode)) 
    { 
      XElement nodeOfInterest = myNode.Elements("nodeOfInterest").FirstOrDefault(); 
      if (nodeOfInterest != null) 
      { 
       nodeOfInterest.Value = "update with this value"; 
      } 
      else 
      { 
       XElement nodeOfInterest = new XElement("nodeOfInterest", "Add nodeOfInterest with this value"); 
       myNode.Add(newElement); 
      } 
    } 

} 
doc.Save("TheFile.xml"); 
+0

, где «элемент» пришел из него, никогда не был объявлен –

+0

элемент должен быть моимNode, я считаю, – mungflesh

+0

извините. Mungflesh прав. Благодарю. – user20358

2

Ну один отправной точкой было бы создать Dictionary<string, XElement> отображение строки идентификатора элемента:

var dictionary = doc.Element("AA").Element("BB").Element("CC").Elements("myNode") 
        .ToDictionary(x => x.Attribute("rowId").Value); 

Тогда:

foreach (User employee in Users) 
{ 
    XElement myNode; 
    if (dictionary.TryGetValue(employee.ID, out myNode)) 
    { 
     // Use myNode 
    } 
    else 
    { 
     // Employee not found 
    } 
} 

Лично я предпочитаю использовать методы выбора, предоставленные LINQ to XML (Elements, Element, Descendants и т. д.), а не SelectSingleNode, SelectChildren и т.д.

+0

спасибо за Ваш ответ. Я все еще не могу обновить узел [elementofInterest] или добавить новый, а затем сохранить весь документ с обновленными/добавленными [elementofInterest] узлами в файловую систему после завершения. – user20358

+0

Что вы подразумеваете под «Я все еще не могу» - что происходит, когда вы пытаетесь? Это должно быть абсолютно нормально. –

+0

Если я понял это правильно, блок if будет иметь весь узел [myNode]. Как только у меня есть весь этот узел в переменной myNode, мне все равно нужно проверить, существует ли элемент [elementofInterest], и если это так, мне нужно его обновить, если нет, мне нужно добавить его. Это нужно сделать для количества итераций в цикле, а затем документ необходимо сохранить – user20358

Смежные вопросы