<p>What's the best way to get the contents of the mixed <code>body</code> element in the code below?  The element might contain either XHTML or text, but I just want its contents in string form.  The <code>XmlElement</code> type has the <code>InnerXml</code> property which is exactly what I'm after.</p>

<p>The code as written <em>almost</em> does what I want, but includes the surrounding <code>&lt;body&gt;</code>...<code>&lt;/body&gt;</code> element, which I don't want.</p>

<pre class="lang-js prettyprint-override"><code>XDocument doc = XDocument.Load(new StreamReader(s));
var templates = from t in doc.Descendants("template")
                where t.Attribute("name").Value == templateName
                select new
                {
                   Subject = t.Element("subject").Value,
                   Body = t.Element("body").ToString()
                };
</code></pre>

[{'answer_id': 3794, 'author': 'Greg Hurlman', 'author_id': 35, 'author_profile': 'https://Stackoverflow.com/users/35', 'pm_score': 0, 'selected': False, 'text': '<p>Is it possible to use the System.Xml namespace objects to get the job done here instead of using LINQ?  As you already mentioned, XmlNode.InnerXml is exactly what you need.</p>\n'}, {'answer_id': 3799, 'author': 'Mike Powell', 'author_id': 205, 'author_profile': 'https://Stackoverflow.com/users/205', 'pm_score': 2, 'selected': False, 'text': "<p>@Greg: It appears you've edited your answer to be a completely different answer.  To which my answer is yes, I could do this using System.Xml but was hoping to get my feet wet with LINQ to XML.</p>\n\n<p>I'll leave my original reply below in case anyone else wonders why I can't just use the XElement's .Value property to get what I need:</p>\n\n<p>@Greg: The Value property concatenates all the text contents of any child nodes.  So if the body element contains only text it works, but if it contains XHTML I get all the text concatenated together but none of the tags.</p>\n"}, {'answer_id': 3896, 'author': 'Mike Powell', 'author_id': 205, 'author_profile': 'https://Stackoverflow.com/users/205', 'pm_score': 3, 'selected': False, 'text': '<p>I ended up using this:</p>\n\n<pre><code>Body = t.Element("body").Nodes().Aggregate("", (b, node) =&gt; b += node.ToString());\n</code></pre>\n'}, {'answer_id': 16882, 'author': 'Vin', 'author_id': 1747, 'author_profile': 'https://Stackoverflow.com/users/1747', 'pm_score': 4, 'selected': False, 'text': '<p>How about using this "extension" method on XElement? worked for me !</p>\n\n<pre><code>public static string InnerXml(this XElement element)\n{\n    StringBuilder innerXml = new StringBuilder();\n\n    foreach (XNode node in element.Nodes())\n    {\n        // append node\'s xml string to innerXml\n        innerXml.Append(node.ToString());\n    }\n\n    return innerXml.ToString();\n}\n</code></pre>\n\n<p>OR use a little bit of Linq </p>\n\n<pre><code>public static string InnerXml(this XElement element)\n{\n    StringBuilder innerXml = new StringBuilder();\n    doc.Nodes().ToList().ForEach( node =&gt; innerXml.Append(node.ToString()));\n\n    return innerXml.ToString();\n}\n</code></pre>\n\n<p><strong>Note</strong>: The code above has to use <code>element.Nodes()</code> as opposed to <code>element.Elements()</code>. Very important thing to remember the difference between the two. <code>element.Nodes()</code> gives you everything like <code>XText</code>, <code>XAttribute</code> etc, but <code>XElement</code> only an Element. </p>\n'}, {'answer_id': 659159, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': '<p>Wondering if (notice I got rid of the b+= and just have b+)</p>\n\n<pre><code>t.Element( "body" ).Nodes()\n .Aggregate( "", ( b, node ) =&gt; b + node.ToString() );\n</code></pre>\n\n<p>might be slightly less efficient than</p>\n\n<pre><code>string.Join( "", t.Element.Nodes()\n                  .Select( n =&gt; n.ToString() ).ToArray() );\n</code></pre>\n\n<p>Not 100% sure...but glancing at Aggregate() and string.Join() in Reflector...I <em>think</em> I read it as Aggregate just appending a returning value, so essentially you get:</p>\n\n<p>string = string + string</p>\n\n<p>versus string.Join, it has some mention in there of FastStringAllocation or something, which makes me thing the folks at Microsoft might have put some extra performance boost in there.  Of course my .ToArray() call my negate that, but I just wanted to offer up another suggestion.</p>\n'}, {'answer_id': 659264, 'author': 'Instance Hunter', 'author_id': 65393, 'author_profile': 'https://Stackoverflow.com/users/65393', 'pm_score': 6, 'selected': False, 'text': "<p>I think this is a much better method (in VB, shouldn't be hard to translate):</p>\n\n<p>Given an XElement x:</p>\n\n<pre><code>Dim xReader = x.CreateReader\nxReader.MoveToContent\nxReader.ReadInnerXml\n</code></pre>\n"}, {'answer_id': 1622498, 'author': 'Ayyash', 'author_id': 63202, 'author_profile': 'https://Stackoverflow.com/users/63202', 'pm_score': 0, 'selected': False, 'text': '<p>you know? the best thing to do is to back to CDATA :( im looking at solutions here but i think CDATA is by far the simplest and cheapest, not the most convenient to develop with tho</p>\n'}, {'answer_id': 1655006, 'author': 'Marcin Kosieradzki', 'author_id': 200228, 'author_profile': 'https://Stackoverflow.com/users/200228', 'pm_score': 3, 'selected': False, 'text': '<p>Keep it simple and efficient:</p>\n\n<pre><code>String.Concat(node.Nodes().Select(x =&gt; x.ToString()).ToArray())\n</code></pre>\n\n<ul>\n<li>Aggregate is memory and performance inefficient when concatenating strings</li>\n<li>Using Join("", sth) is using two times bigger string array than Concat... And looks quite strange in code.</li>\n<li>Using += looks very odd, but apparently is not much worse than using \'+\' - probably would be optimized to the same code, becase assignment result is unused and might be safely removed by compiler.</li>\n<li>StringBuilder is so imperative - and everybody knows that unnecessary "state" sucks.</li>\n</ul>\n'}, {'answer_id': 1704579, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 9, 'selected': True, 'text': '<p>I wanted to see which of these suggested solutions performed best, so I ran some comparative tests. Out of interest, I also compared the LINQ methods to the plain old <strong>System.Xml</strong> method suggested by Greg. The variation was interesting and not what I expected, with the slowest methods being <strong>more than 3 times slower than the fastest</strong>.</p>\n\n<p>The results ordered by fastest to slowest:</p>\n\n<ol>\n<li>CreateReader - Instance Hunter (0.113 seconds)</li>\n<li>Plain old System.Xml - Greg Hurlman (0.134 seconds)</li>\n<li>Aggregate with string concatenation - Mike Powell (0.324 seconds)</li>\n<li>StringBuilder - Vin (0.333 seconds)</li>\n<li>String.Join on array - Terry (0.360 seconds)</li>\n<li>String.Concat on array - Marcin Kosieradzki (0.364)</li>\n</ol>\n\n<hr>\n\n<p><strong>Method</strong></p>\n\n<p>I used a single XML document with 20 identical nodes (called \'hint\'):</p>\n\n<pre><code>&lt;hint&gt;\n  &lt;strong&gt;Thinking of using a fake address?&lt;/strong&gt;\n  &lt;br /&gt;\n  Please don\'t. If we can\'t verify your address we might just\n  have to reject your application.\n&lt;/hint&gt;\n</code></pre>\n\n<p>The numbers shown as seconds above are the result of extracting the "inner XML" of the 20 nodes, 1000 times in a row, and taking the average (mean) of 5 runs. I didn\'t include the time it took to load and parse the XML into an <code>XmlDocument</code> (for the <strong>System.Xml</strong> method) or <code>XDocument</code> (for all the others).</p>\n\n<p>The LINQ algorithms I used were: <em>(C# - all take an <code>XElement</code> "parent" and return the inner XML string)</em></p>\n\n<p><strong>CreateReader:</strong></p>\n\n<pre class="lang-js prettyprint-override"><code>var reader = parent.CreateReader();\nreader.MoveToContent();\n\nreturn reader.ReadInnerXml();\n</code></pre>\n\n<p><strong>Aggregate with string concatenation:</strong></p>\n\n<pre class="lang-js prettyprint-override"><code>return parent.Nodes().Aggregate("", (b, node) =&gt; b += node.ToString());\n</code></pre>\n\n<p><strong>StringBuilder:</strong></p>\n\n<pre class="lang-js prettyprint-override"><code>StringBuilder sb = new StringBuilder();\n\nforeach(var node in parent.Nodes()) {\n    sb.Append(node.ToString());\n}\n\nreturn sb.ToString();\n</code></pre>\n\n<p><strong>String.Join on array:</strong></p>\n\n<pre class="lang-js prettyprint-override"><code>return String.Join("", parent.Nodes().Select(x =&gt; x.ToString()).ToArray());\n</code></pre>\n\n<p><strong>String.Concat on array:</strong></p>\n\n<pre class="lang-js prettyprint-override"><code>return String.Concat(parent.Nodes().Select(x =&gt; x.ToString()).ToArray());\n</code></pre>\n\n<p>I haven\'t shown the "Plain old System.Xml" algorithm here as it\'s just calling .InnerXml on nodes.</p>\n\n<hr>\n\n<p><strong>Conclusion</strong></p>\n\n<p>If performance is important (e.g. lots of XML, parsed frequently), I\'d <strong>use Daniel\'s <code>CreateReader</code> method every time</strong>. If you\'re just doing a few queries, you might want to use Mike\'s more concise Aggregate method.</p>\n\n<p>If you\'re using XML on large elements with lots of nodes (maybe 100\'s), you\'d probably start to see the benefit of using <code>StringBuilder</code> over the Aggregate method, but not over <code>CreateReader</code>. I don\'t think the <code>Join</code> and <code>Concat</code> methods would ever be more efficient in these conditions because of the penalty of converting a large list to a large array (even obvious here with smaller lists).</p>\n'}, {'answer_id': 2460802, 'author': 'Martin R-L', 'author_id': 46343, 'author_profile': 'https://Stackoverflow.com/users/46343', 'pm_score': 2, 'selected': False, 'text': '<p>Personally, I ended up writing an <code>InnerXml</code> extension method using the Aggregate method:</p>\n\n<pre><code>public static string InnerXml(this XElement thiz)\n{\n   return thiz.Nodes().Aggregate( string.Empty, ( element, node ) =&gt; element += node.ToString() );\n}\n</code></pre>\n\n<p>My client code is then just as terse as it would be with the old System.Xml namespace:</p>\n\n<pre><code>var innerXml = myXElement.InnerXml();\n</code></pre>\n'}, {'answer_id': 3474630, 'author': 'Shivraj', 'author_id': 419273, 'author_profile': 'https://Stackoverflow.com/users/419273', 'pm_score': -1, 'selected': False, 'text': '<pre><code>public static string InnerXml(this XElement xElement)\n{\n    //remove start tag\n    string innerXml = xElement.ToString().Trim().Replace(string.Format("&lt;{0}&gt;", xElement.Name), "");\n    ////remove end tag\n    innerXml = innerXml.Trim().Replace(string.Format("&lt;/{0}&gt;", xElement.Name), "");\n    return innerXml.Trim();\n}\n</code></pre>\n'}, {'answer_id': 14164352, 'author': 'Todd Menier', 'author_id': 62600, 'author_profile': 'https://Stackoverflow.com/users/62600', 'pm_score': 4, 'selected': False, 'text': '<p>With all due credit to those who discovered and proved the best approach (thanks!), here it is wrapped up in an extension method:</p>\n\n<pre><code>public static string InnerXml(this XNode node) {\n    using (var reader = node.CreateReader()) {\n        reader.MoveToContent();\n        return reader.ReadInnerXml();\n    }\n}\n</code></pre>\n'}, {'answer_id': 21642095, 'author': 'user950851', 'author_id': 950851, 'author_profile': 'https://Stackoverflow.com/users/950851', 'pm_score': 1, 'selected': False, 'text': '<p>// using Regex might be faster to simply trim the begin and end element tag</p>\n\n<pre><code>var content = element.ToString();\nvar matchBegin = Regex.Match(content, @"&lt;.+?&gt;");\ncontent = content.Substring(matchBegin.Index + matchBegin.Length);          \nvar matchEnd = Regex.Match(content, @"&lt;/.+?&gt;", RegexOptions.RightToLeft);\ncontent = content.Substring(0, matchEnd.Index);\n</code></pre>\n'}, {'answer_id': 26348079, 'author': 'user1920925', 'author_id': 1920925, 'author_profile': 'https://Stackoverflow.com/users/1920925', 'pm_score': 1, 'selected': False, 'text': '<p>doc.ToString() or doc.ToString(SaveOptions) does the work.\nSee <a href="http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx</a></p>\n'}, {'answer_id': 52996448, 'author': 'Vinod Srivastav', 'author_id': 3057246, 'author_profile': 'https://Stackoverflow.com/users/3057246', 'pm_score': 0, 'selected': False, 'text': '<pre><code>var innerXmlAsText= XElement.Parse(xmlContent)\n                    .Descendants()\n                    .Where(n =&gt; n.Name.LocalName == "template")\n                    .Elements()\n                    .Single()\n                    .ToString();\n</code></pre>\n\n<p>Will do the job for you</p>\n'}]
['https://Stackoverflow.com/questions/3793', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/205/']