1

My XML Document is as below -

<?xml version="1.0" encoding="utf-8"?>
<Parents>
    <Parent id="A" description="A is a parent">
        <Children>
            <ChildName name = "Son1ofA" />
            <ChildName name = "Son2ofA" />
        </Children>
    </Parent>
</Parents>

Requirement -

  1. To identify the Element "Parent", clone it. Change the attribute id to "B". Add it as a sibling to itself (making it a new child of "Parents").
  2. The output file is as below -

    <Parents>
    <Parent id="A" description="A is a parent">
        <Children>
            <ChildName name = "Son" />
            <ChildName name = "Daughter" />
        </Children>
    </Parent>
    <Parent id="B" description="A is a parent">
        <Children>
            <ChildName name = "Son" />
            <ChildName name = "Daughter" />
        </Children>
    </Parent>
    

My Code

XDocument myXMLDocument = XDocument.Load("File.xml");
XElement myParentsElement = myXMLDocument.Element("Parents");
XElement myFirstParentElement = myParentsElement.Element("Parent");
XElement myNewParentElement = new XElement(myFirstParentElement);
XAttribute myParentId = myNewParentElement.Attribute("id");
myParentId.Value = "B";
myFirstParentElement.AddAfterSelf(myNewParentElement);
myXMLDocument.Save("NewFile.xml");

And it works perfectly fine, without any issues. Clearly, this is no good programming. Because, I am extracting the Element Parents, then using that as a root node, I am extracting Parent etc.,

What I would want to be able to do is something like this - Directly key in the path - as in /Parents/Parent(XPath), extract that particular Node, make a copy of it, make modifications to its attributes, add it as a sibling and save the Document.

Am I doing something silly?

2 Answers 2

3

I wouldn't say you're doing something "silly" but there are ways to clone a node and modify it in a more streamlined way with LINQ. Depending on what your goals are, you can use a function to modify the node and some handy LINQ expressions to clone it. Here is an example based on what you've done above:

        XDocument doc = XDocument.Parse(@"<?xml version='1.0' encoding='utf-8'?>
        <Parents>
            <Parent id='A' description='A is a parent'>
                    <Children>
                            <ChildName name = 'Son1ofA' />
                            <ChildName name = 'Son2ofA' />
                    </Children>
            </Parent>
        </Parents>
        ");

        Func<XElement, XElement> trans = (x) => {
            char c = Convert.ToChar(x.Attribute("id").Value);
            int inc = (int)c;
            x.Attribute("id").Value = Convert.ToChar(++inc).ToString();
            return x;
        };
        string elementTarget = "Parent"; // assume you read this from some input
        doc.Root.ReplaceWith(new XElement(doc.Root.Name,
                                doc.Descendants(elementTarget).Select(p => p),
                                doc.Descendants(elementTarget).Select(p => trans(p))));

        Console.Write(doc);
        Console.ReadLine();

You can see the logic for transforming in the "trans" anonymous function and the ability to arbitrarily select a node using the Descendants enumeration in LINQ. This solution is somewhat brittle but perhaps it can give you some ideas.

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

Comments

2

If you want to use XPath in Linq-to-xml, here are some extension methods that will be help.

using System.Xml.XPath;

XDocument.Load("file name").XPathSelectElement("XPath");

Comments

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.