Reputation: 14736
I have an XML file in the following format
<?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>
I want to use Linq to pick out one node by the name 'MyNode' where the rowid is a particular number that I will be getting from a collection in an object. Once I get myNode I want to update the value of the child nodeOfInterest if it is present. If not present, then I would like to add it. Once done I want to save the file.
This is what I have at the moment but it may not be the right approach.
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
{
}
}
Is there a way this can be done using a direct join between the List and the xmldoc in memory? This will be a large list and an equally large xml file. I dont think running a loop and calling selectSingleNode is the most efficient way.
Thanks for your inputs
Upvotes: 0
Views: 86
Reputation: 14736
The full answer, with help from Jon's replies...
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");
Upvotes: 0
Reputation: 1499770
Well one starting point would be to create a Dictionary<string, XElement>
mapping the row ID to the element:
var dictionary = doc.Element("AA").Element("BB").Element("CC").Elements("myNode")
.ToDictionary(x => x.Attribute("rowId").Value);
Then:
foreach (User employee in Users)
{
XElement myNode;
if (dictionary.TryGetValue(employee.ID, out myNode))
{
// Use myNode
}
else
{
// Employee not found
}
}
Personally I prefer using the selection methods provided by LINQ to XML (Elements
, Element
, Descendants
etc) rather than SelectSingleNode
, SelectChildren
etc.
Upvotes: 2