Reputation: 1476
I have an XML which look like this,
<Names>
<Name>
<FName>Abc</FName>
<LName>XYZ</LName>
</Name>
<Name>
<FName>Abc2</FName>
<LName>XYZ2</LName>
</Name>
<Name>
<FName>Abc3</FName>
<LName>XYZ3</LName>
</Name>
<Name>
<FName>Abc4</FName>
<LName>XYZ4</LName>
</Name>
</Names>
I am trying to change the Node names prophetically in c# if their occurrence is more than once and Except the first node. First node name remains same;
after processing XML should look like this;
<Names>
<Name> // kepp first node name same
<FName>Abc</FName>
<LName>XYZ</LName>
</Name>
<ChildName> //changed
<FName>Abc2</FName>
<LName>XYZ2</LName>
</ChildName>
<ChildName> //changed
<FName>Abc3</FName>
<LName>XYZ3</LName>
</ChildName>
<ChildName> // changed
<FName>Abc4</FName>
<LName>XYZ4</LName>
</ChildName>
</Names>
Node of Name can be one, if it is once, keep the same, if more than leave the first and change the names of others.
I am trying like this XML object is of IEnumerable<XElement>
type;
//check if NAME node occurs multiple times, make other to child.
var nameCounts = element.Descendants().Where(x => x.Name.LocalName == "Name");
int number = nameCounts.Count();
if (number > 1) // if occurance more than one
{
foreach (var e in element.Descendants().Where(x => x.Name.LocalName == "Name").ToList())
{
//e.NodesAfterSelf();
// unable to understand what to do
}
}
UPDATE:
However I got the answer of my question; I made a little mistake actually my XML look like this;
<ListOfNames>
<Names>
<Name> // two occurrence, 2nd will change to CHILD NAME
<FName>Abc</FName>
<LName>XYZ</LName>
</Name>
<Name>
<FName>Abc2</FName>
<LName>XYZ2</LName>
</Name>
</Names>
<Names> // three occurrence, 2nd and 3rd will change to CHILDNAME
<Name>
<FName>Abc</FName>
<LName>XYZ</LName>
</Name>
<Name>
<FName>Abc2</FName>
<LName>XYZ2</LName>
</Name>
<Name>
<FName>Abc2</FName>
<LName>XYZ2</LName>
</Name>
</Names>
<Names> // only one occurrence, nothing change
<Name>
<FName>Abc</FName>
<LName>XYZ</LName>
</Name>
</Names>
</ListOfNames>
Upvotes: 2
Views: 142
Reputation: 1500055
It's simpler than you're currently making it. All you need to do is skip the first Name
element, and change the name of the rest. To cope with multiple Names
elements, just find each one of those with doc.Descendants("Names")
and work on the elements within that container.
Here's code to do exactly that:
using System;
using System.Linq;
using System.Xml.Linq;
public class Test
{
public static void Main(string[] args)
{
var doc = XDocument.Load("test.xml");
// Handle each Names element separately
foreach (var container in doc.Descendants("Names"))
{
// Within a names element, find all the Name elements,
// and materialize the query. (That may not be necessary; see later.)
var names = container.Elements("Name").ToList();
// Skip the first name, but modify each of the rest.
foreach (var element in names.Skip(1))
{
element.Name = "ChildName";
}
}
Console.WriteLine(doc);
}
}
The ToList()
call may not be necessary. LINQ to XML isn't terribly clear (to me, anyway) in terms of whether changes made to the document while you're iterating over the query are problematic or not. I've certainly seen cases where I'd expect it not to be problematic, but it does cause problems - and vice versa. If you know that your document will be small enough that materializing the results won't actually cause problems, I'd typically do so just to avoid having to investigate further.
Upvotes: 3