More on XML Namespaces in VB....

Posted Sun, Dec 9 2007 23:20 by bill

A couple of weeks ago I wrote about XML Namespace issues in VB: one in particular was to do with namespace declarations being repeated in the output XML.  In those cases we only looked at common namespaces for the entire document.

However the example of creating a word document I posted earlier today raises a similar issue, but this time it's with namespaces that are used in child elements not in the root element.  Previously, one suggested workaround was to Import namespaces, and use expression placeholders, but as the word document shows, this does not produce what is often the desirable outcome. 

The following simplified example demonstrates this:

- the goal of this exercise is to output the following XML:

<?xml version="1.0"?>

<a:root xmlns:a="url:a" xmlns:b="url:b">

    <b:x></b:x>

    <b:y></b:y>

</a:root>

The constraint is we want to create the x and y elements separately and insert them into the root element. .eg:

 

Imports <xmlns:a="url:a">

Imports <xmlns:b="url:b">

 

.....

   Dim el1 = <b:x></b:x>

   Dim el2 = <b:y></b:y>

 

   Dim doc = <?xml version="1.0"?>

             <a:root>

                <%= el1 %>

                <%= el2 %>

             </a:root>

 

However that doesn't work. The output for that repeats the namespace of the b.

<a:root xmlns:a="url:a">

   <b:x xmlns:b="url:b"></b:x>

   <b:y xmlns:b="url:b"></b:y>

</a:root>

 

So I thought I would try declaring the b namespace in the root element:

 

      Dim doc = <?xml version="1.0"?>

               <a:root xmlns:b="url:b">

                  <%= el1 %>

                  <%= el2 %>

               </a:root>

 

Now that works. That gives the correct output of :

<a:root xmlns:a="url:a" xmlns:b="url:b">

    <b:x></b:x>

    <b:y></b:y>

</a:root>


But what is going on here you may ask ?  Why does this work ?  Well VB removes xmlns attributes from the added elements for any declarations that are used in the containing node. So the minimal fix to get my word document have the namespace declarations at the start requires the correct injection of namespaces to the parent they are added to.  For example :

 

 Dim thirdParagraph = <w:p

                          xmlns:dm="http://schemas.openxmlformats.org/drawingml/2006/main"

                          xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"

                          xmlns:dp="http://schemas.openxmlformats.org/drawingml/2006/picture"

                          xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">

                          <w:r><%= drawing %></w:r>

                      </w:p>

 

I also had to re-declare 2 xml namespaces in the drawing variables; for the document I had to add 5. And that is in just a simple example.  What's really annoying is those namespaces were Imported at the module level in the first place. It would have been nice to write that XML literal using the imported namespaces, e.g:

 

Dim thirdParagraph = <w:p <%= dm %><%= wp %><%= dp %><%= r %>>

                           <w:r><%= drawing %></w:r>

                      </w:p>

 

Alas that doesn't work.  Nor does and combination of GetXMLNamespace  that I could think of. 

In the need I decided it was a lot easier to just add the namespaces once to the root document and remove all of them from added elements, using a modified extension method.

 

 

<Runtime.CompilerServices.Extension()> _

 Function RemoveAllNS(ByVal el As XElement, Optional ByVal includeChildNodes As Boolean = False) As XElement

      Dim current = el.LastAttribute

      Do While current IsNot Nothing

         Dim temp = current.PreviousAttribute

         If current.IsNamespaceDeclaration Then

            current.Remove()

         End If

         current = temp

      Loop

      If includeChildNodes Then

         For Each child In el.Descendants

            RemoveAllNS(child)

         Next

      End If

      Return el

   End Function

 

 

 

It's a shame this doesn't work easier than this :(

Filed under: , , ,

Comments

# Removing duplicate namespaces in XML Literals (Shyam Namboodiripad)

Wednesday, June 16, 2010 1:56 PM by The Visual Basic Team

A common problem that one often runs into with XML literals and the LINQ to XML API is duplicate XML