0

I have a XML document that looks like this:

<Person>
  <LastName>LastName1</LastName>
  <FirstName>FirstName1</FirstName>
  <MiddleName>MiddleName1</MiddleName>
</Person>

Originally I had a method to create this structure like below:

public XElement ToXML()
{
  return new XElement("Person",
    new XElement(this.LastName.ToXML()),
    new XElement(this.FirstName.ToXML()),
    new XElement(this.MiddleName.ToXML()));
}

The problem is there are a lot of other nodes other than just Person that use the Name values within the root. So what I tried doing was refactoring out the FirstName, LastName, and MiddleName elements to be in their own reusable class with a ToXMLDoc() method that returns those elements as a XDocument instead of a XElement (since the root will be dictated by the class needing the name children; might be Person, Employee, etc.)

This is what my new ToXMLDoc returns:

return new XDocument(new XElement(this.LastName.ToXML()),
                     new XElement(this.FirstName.ToXML()),
                     new XElement(this.MiddleName.ToXML()));

My problem is I want to now add this content to within the root XElement added by my Person class. I tried doing something like below, but I'm not using the constructor properly and getting a "Ambiguous constructor reference" error.

return new XElement("Person",
    foreach (XElement xe in NameType.ToXMLDoc().Nodes())
    {
      new XElement(xe.Value);
    }
);

How can I take the contents from the ToXMLDoc() method and add them to the XElement node being created for Person? Any help is appreciated, thanks!

atconway
  • 20,624
  • 30
  • 159
  • 229

2 Answers2

1

You're currently trying to embed a foreach loop within a constructor call. That's not going to work - but it's actually pretty simple:

return new XElement("Person", NameType.ToXMLDoc()
                                      .Nodes()
                                      .Select(xe => new XElement(xe.Value));

Are you sure you don't just want to copy the elements wholesale though? In which case it would just be:

return new XElement("Person", NameType.ToXMLDoc().Nodes());
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Was using the `XDocument` to hold the (3) individual name nodes in the `ToXMLDoc` method the appropriate type, or would you have gone with something else like `List` instead? – atconway Feb 04 '13 at 15:06
  • @atconway: It's really unclear what you're trying to achieve, to be honest. If all you need it three names, why aren't you using a `List` instead? – Jon Skeet Feb 04 '13 at 15:12
  • I'm creating individual classes that when composed can create XDocuments for the purposes of sending messages. There are many different messages so the classes must remain flexible and all use the XElement (composable children) and XDocument (main message doing the composition) types. This class containing the individual 'NameType' elements must return those XElement values and then be used by 1..n classes that will dictate it's root value. Your solution for the way I have it now using a `XDocument` works, but wondered if using `List` is preferred? Then I need that solution. – atconway Feb 04 '13 at 15:26
  • 1
    @atconway: Sorry, you've given lots of little details, but not enough context to really understand your system. If what I've given works for you, then I'd go with that. You can easily create a `List` if you want to later. – Jon Skeet Feb 04 '13 at 15:28
  • By the way doing it wholesale as you inquired about was the way I wanted (didn't know it could be done like that), but the other method is nice to know. Thank you for helping. – atconway Feb 04 '13 at 15:36
0

I would return an XElement, rather than an XDocument

This way you could just do:

new XElement("Person", NameType.ToXMLDoc())
paul
  • 21,653
  • 1
  • 53
  • 54
  • How can I return a `XElement` type when I do not have a root, but rather a collection of root nodes? (i.e. it's only LastName, FirstName, MiddelName with no root element). I moved up to a `XDocument` that could contain all the individual nodes. – atconway Feb 04 '13 at 15:02
  • Yes, you are correct. I would probably return something like – paul Feb 04 '13 at 15:04
  • Yep, only thing is then I would always need to remember to strip off that `` root because it needs to be `` or whatever as dictated by the calling class that needs the child name nodes. – atconway Feb 04 '13 at 15:08
  • I just don't like creating non-compliant XDocuments. Maybe I'd go with a `List` or something then. The method Jon S suggested is absolutely fine. – paul Feb 04 '13 at 15:10