views:

632

answers:

5

Hi,

I'm a C# developer who's fumbling in the first VB code he's written since VB6, so if I am asking a rather obvious question, please forgive me.

I decided to experiment with XML Literals to generate some XML code for me, instead of using XMLDocument

I have 2 questions, the second regarding a workaround due to my inability to figure out the first.

1: Ideal solution

I have a Dictionary of ElementName, ElementValue whose KeyValue pairs I was looping over in the hope of generating the values dynamically, but the following syntax dies a horrible death

Dim xConnections As XElement        
For Each connection As Connection In connections.AsList
    For Each kvp As KeyValuePair(Of String, String) In connection.DecompiledElements
        xConnections = <Connections> <<%= kvp.Key %>><%= kvp.Value %><\<%=kvp.Key %>>  </Connections>
    Next
Next

I have vague memories of the T4 syntax (the <%=%> syntax) being able to handle more complex operations (rather than direct assignment to the <%= ) and a 'Response.Write' like object to write output to, but I can't remember the details.

2: Cludgy workaround

Instead I thought of building a StringBuilder object and assigning its .ToString to the XElement, but that also failed with a conversion error.

I would prefer to continue using my key value pair concept in example one above, as I feel cludging together a string as in example 2 above is rather nasty, and I really should go back to using XMLDocument if instead.

Any thoughts or assistance greatly appreciated

A: 

If I understand correctly what you are trying to do, you can use the StringBuilder. Use the StringBuilder.Append method and append the XmlElement 'OuterXml' property.

For example:

sb.Append(xmlElement.OuterXml)

DaveK
A: 

@DaveK, thanks, that certainly answers part two of the question, and when I get enough repuation, I will upmod that answer.

I will refrain from setting it to 'the answer' for the moment, so not as to discourage people from answering the first part of the question.

johnc
A: 

We would all be remiss not to mention that dynamic XML element names are generally a bad idea. The whole point of XML is to create a store a data structure in a form that is readily:

  1. Verifiable
  2. Extendable

Dynamic element names fail that first condition. Why not simply use a standard XML format for storing key/value pairs like plists?

<dict>
    <key>Author</key>
    <string>William Shakespeare</string>
    <key>Title</key>
    <string>Romeo et</string>
    <key>ISBN</key>
    <string>?????</string>
</dict>
Frank Krueger
These are not dynamic element names at all, the element names in the dictionary are all specified in an xsd
johnc
+3  A: 

VB.NET XML Literals are very powerful, but most often adding some LINQ to them makes them truly awesome. This code should do exactly what you're trying to do.

Dim Elements = New Dictionary(Of String, String)
Elements.Add("Key1", "Value1")
Elements.Add("Key2", "Value2")
Elements.Add("Key3", "Value3")

Dim xConnections = <Connections>
                       <%= From elem In Elements _
                           Select <<%= elem.Key %>><%= elem.Value %></> %>
                   </Connections>

The empty closing tag </> is all that is needed for the vb compiler to properly construct an xml element who's name is generated from a value within a <%= %> block.

Calling xConnections.ToString renders the following:

<Connections>
    <Key1>Value1</Key1>
    <Key2>Value2</Key2>
    <Key3>Value3</Key3>
</Connections>
Dennis Palmer
A: 

To answer this more completely...

When injecting Strings into an XML Literal, it will not work properly unless you use XElement.Parse when injecting an XElement (this is because special characters are escaped)

So your ideal solution is more like this:

Dim conns = connections.AsList()
If conns IsNot Nothing AndAlso conns.length > 0 Then
    Dim index = 0
    Dim xConnections = _
        <Connections>
            <%= From kvp As KeyValuePair(Of String, String) In conns (System.Threading.Interlocked.Increment(index)).DecompiledElements() _
            Select XElement.Parse("<" & <%= kvp.Key %> & ">" & <%= kvp.Value %> & "</" & <%= kvp.Key %> & ">") _
             %>
        </Connections>
    Return xConnections.ToString()
End If

ToString will return the OuterXML Properly as a String (Value will not...) of course, just drop the ToString() if you want to return an XElement of

Since I don't know what AsList() does, nor do I know what DecompiledElements do, set your error trapping accordingly. There are other ways to do the loops as well, this is just one solution.