2

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>
2
  • I have made a mistake in question, can you please guide , my XML have <ListOfNames> as parent node it has several <Names> nodes containing values as written, then how would I change node names in all <Names> except first occurrence of <Name> Commented May 10, 2018 at 10:17
  • updated question: Commented May 10, 2018 at 10:26

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

10 Comments

ToList() seems not necessary here.
@Evk: I've never become confident enough in when it's important for LINQ to XML queries that change the results and when it's not. I usually find it's safer to just materialize the query and not worry about it. I'll add a comment.
Well you are not adding\removing elements, so it's safe. But I see your point.
@Evk: It's changing the name of elements, when the query is on the name of elements, so it's changing the logical results of the query. As it's only changing the current element, it may be okay... but I've been surprised before.
@trighati: I've edited my answer. In future if the question changes significantly after it's been answered, it may well be clearer to ask a new question. I've managed to edit my answer so that it handles both scenarios, but it would be good to take more care over the question to start with.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.