{"id":4443,"date":"2008-05-01T19:50:00","date_gmt":"2008-05-01T19:50:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2008\/05\/01\/vb-xml-cookbook-recipe-4-get-inner-xml-from-the-nodes-property-doug-rothaus\/"},"modified":"2024-07-05T14:25:47","modified_gmt":"2024-07-05T21:25:47","slug":"vb-xml-cookbook-recipe-4-get-inner-xml-from-the-nodes-property-doug-rothaus","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/vb-xml-cookbook-recipe-4-get-inner-xml-from-the-nodes-property-doug-rothaus\/","title":{"rendered":"VB XML Cookbook, Recipe 4: Get Inner XML from the Nodes Property (Doug Rothaus)"},"content":{"rendered":"<p class=\"MsoNormal\"><a href=\"http:\/\/blogs.msdn.com\/vbteam\/archive\/2008\/04\/25\/vb-xml-cookbook-recipe-3-identity-transforms-doug-rothaus.aspx\"><font face=\"Calibri\" size=\"3\">Recipe 3<\/font><\/a><font face=\"Calibri\" size=\"3\"> showed one way to work with mixed XML content using the <\/font><a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/bb384876.aspx\"><font face=\"Calibri\" size=\"3\">XML Descendant axis property<\/font><\/a><font face=\"Calibri\" size=\"3\"> and the <\/font><a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/system.xml.linq.xnode.replacewith.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">ReplaceWith<\/font><\/a><font face=\"Calibri\" size=\"3\"> method. This is one way to do an identity transform and we&rsquo;ll look at another method in a later post. There is a key capability not mentioned in Recipe 3 that you will need for fully-functioning identity transforms. That is the concept of copying the inner XML of an element. You get the inner XML of an element from the <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xml.linq.xcontainer.nodes.aspx\"><font face=\"Calibri\" size=\"3\">Nodes<\/font><\/a><font face=\"Calibri\" size=\"3\"> property.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Recipe 3 transformed e-mail objects from our AdventureWorks sample document into hyper-links in an HTML document and preserved the original formatting by performing an identity transform.<span>&nbsp; <\/span>To keep things simple in Recipe 3, however, I left out the fact that the schema for the <\/font><span>&lt;eMailAddress&gt;<\/span><font face=\"Calibri\" size=\"3\"> element (found in the ContactTypes.xsd schema file) allows for both an <\/font><span>&lt;eMail&gt;<\/span><font face=\"Calibri\" size=\"3\"> element that contains the e-mail address, and also a <\/font><span>&lt;SpecialInstructions&gt;<\/span><font face=\"Calibri\" size=\"3\"> element for additional instructions such as phone numbers to use in place of an e-mail, when to call, and so on. The <\/font><span>&lt;SpecialInstructions&gt;<\/span><font face=\"Calibri\" size=\"3\"> element can contain any of the other elements identified in ContactTypes.xsd. To include all of the information for an <\/font><span>&lt;eMailAddress&gt;<\/span><font face=\"Calibri\" size=\"3\"> element, we must also include any special instructions. (Note: You can download the XML document and related schemas from the <\/font><a href=\"http:\/\/blogs.msdn.com\/vbteam\/archive\/2008\/02\/21\/vb-xml-cookbook-recipe-1-xml-transformations-using-xml-literals-replacing-xsl-for-each-doug-rothaus.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">Recipe 1<\/font><\/a><font face=\"Calibri\" size=\"3\"> post).<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Transforming the <\/font><span>&lt;eMail&gt;<\/span><font face=\"Calibri\" size=\"3\"> element from an e-mail address is simple because the <\/font><span>&lt;eMail&gt;<\/span><font face=\"Calibri\" size=\"3\"> element contains only the e-mail address value. However, transforming the <\/font><span>&lt;SpecialInstructions&gt;<\/span><font face=\"Calibri\" size=\"3\"> element is not as simple because the element value can contain sub- elements as well as values. If you embedded the <b>Value<\/b> of a <\/font><span>&lt;SpecialInstructions&gt;<\/span><font face=\"Calibri\" size=\"3\"> element, you would get the text found within the element, but any XML found would be stripped out. This is also referred to as the inner text of an element. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">If you&rsquo;re familiar with the classes in the <b>System.Xml<\/b> namespace, you will immediately recognize this behavior. The solution is to embed the inner XML of the element rather than the inner text (the <b>Value<\/b> property). While the <b>System.Xml<\/b> classes expose both <b>InnerText<\/b> and <b>InnerXml<\/b> properties, LINQ to XML does not. Inner text is returned from the <b>Value<\/b> property, and inner XML is returned from the <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xml.linq.xcontainer.nodes.aspx\"><font face=\"Calibri\" size=\"3\">Nodes<\/font><\/a><font face=\"Calibri\" size=\"3\"> property. Why the difference? The <b>InnerXml<\/b> property returns a string of XML, which would have to be re-parsed into XML objects. The <b>Nodes<\/b> property returns a collection of LINQ to XML objects, which you can manipulate or embed as a whole into XML Literals making the <b>Nodes<\/b> property a powerful tool for transforming XML.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">So, with all of this in mind, let&rsquo;s look at both the <b>Value<\/b> (inner text) and <b>Nodes<\/b> (inner XML) properties in an example. Here we have a function (template), <b>TransformEmail<\/b>, that transforms the XML source into HTML. The e-mail address is retrieved using the Value property and also a call to the <b>GetSpecialInstructions<\/b> function to embed the HTML for any special instructions that may be included. The <b>GetSpecialInstructions<\/b> method returns HTML markup and the inner XML of the<\/font><span> &lt;SpecialInstructions&gt;<\/span><font face=\"Calibri\" size=\"3\"> element as it can contain mixed markup including text, or other XML.<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;<\/span><span>Private<\/span> <span>Sub<\/span> TransformEmail(<span>ByVal<\/span> email <span>As<\/span> XElement)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp; <\/span><span>Dim<\/span> emailHtml = <span>&lt;<\/span><span>div<\/s> <span>class<\/span><span>=<\/span><span>&#8220;<\/span><span>Email<\/span><span>&#8220;<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>a<\/span> <span>href<\/span><span>=<\/span><span>&lt;%=<\/span> <span>&#8220;mailto:&#8221;<\/span> &amp; email.<span>&lt;<\/span>act:eMailAddress<span>&gt;<\/span>.Value <span>%&gt;<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;%=<\/span> email.<span>&lt;<\/span>act:eMailAddress<span>&gt;<\/span>.Value <span>%&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;\/<\/span><span>a<\/span><span>&gt;<\/span><span>&#032;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;%=<\/span> GetSpecialInstructions(email.<span>&lt;<\/span>act:SpecialInstructions<span>&gt;<\/span>) <span>%&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;\/<\/span><span>div<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;&nbsp; <\/span>email.ReplaceWith(emailHtml)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;<\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&nbsp;<\/span><span>Private<\/span> <span>Function<\/span> GetSpecialInstructions( _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>ByVal<\/span> instructions <span>As<\/span> IEnumerable(<span>Of<\/span> XElement)) <span>As<\/span> IEnumerable(<span>Of<\/span> XElement)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> instructions <span>IsNot<\/span> <span>Nothing<\/span> <span>Then<\/span> _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;<\/span><span>Return<\/span> <span>From<\/span> instruction <span>In<\/span> instructions _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>Select<\/span> <span>&lt;<\/span><span>span<\/span> <span>class<\/span><span>=<\/span><span>&#8220;<\/span><span>SpecialInstructions<\/span><span>&#8220;<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>&lt;%=<\/span> instruction.Nodes <span>%&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>&lt;\/<\/span><span>span<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>Nothing<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recipe 3 showed one way to work with mixed XML content using the XML Descendant axis property and the ReplaceWith method. This is one way to do an identity transform and we&rsquo;ll look at another method in a later post. There is a key capability not mentioned in Recipe 3 that you will need for [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[59,94,117,163,166,185],"class_list":["post-4443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic","tag-doug-rothaus","tag-linqvb9","tag-orcas","tag-vb-xml-cookbook","tag-vb2008","tag-xml"],"acf":[],"blog_post_summary":"<p>Recipe 3 showed one way to work with mixed XML content using the XML Descendant axis property and the ReplaceWith method. This is one way to do an identity transform and we&rsquo;ll look at another method in a later post. There is a key capability not mentioned in Recipe 3 that you will need for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4443","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=4443"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4443\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=4443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=4443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=4443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}