Visual Basic .NET (since version 9) can contain XML written directly in an expression. The compiler turns it into System.Xml.Linq objects (XElement, XDocument, XComment, XProcessingInstruction, XCData), so a program can build and query XML without strings. It is the one place where the lexical rules of the language change: inside an XML literal the text is read by XML rules, and Visual Basic code comes back only inside <%= … %>.
Literals
Imports System.Xml.Linq
Imports <xmlns:db="http://example.com/db">
Dim name = "Ada"
Dim ages = {36, 41}
Dim people = <people>
<%= From a In ages Select <person age=<%= a %>><%= name %></person> %>
</people>
Dim doc = <?xml version="1.0" encoding="utf-8"?>
<!-- a comment -->
<db:root id="r1">
<item kind="a">one</item>
<item kind="b"><![CDATA[x < y]]></item>
<empty/>
</db:root>
Dim el As XElement = <a b="1"/>
| Form | Becomes |
|---|---|
<name attr="v">…</name>, <name/> | an XElement; an end tag may be written </> to close the nearest open element |
<?xml version="1.0"?> then an element | an XDocument (a document literal needs the XML declaration; comments and processing instructions may come before the root element) |
<!-- text --> | an XComment |
<?target data?> | an XProcessingInstruction |
<![CDATA[ … ]]> | an XCData; its text is taken literally |
text and & < A | character data; the predefined and numeric character references are understood |
<%= expression %> | an embedded Visual Basic expression: in content, as an attribute value (with or without quotes), as an element or attribute name, or in a comment or CDATA; the value may be a string, an object, a sequence (each element is added) or Nothing (nothing is added) |
Line breaks are white space in XML, so no continuation is needed between the parts of a literal; white space is preserved only as character data inside an element (the indentation between two elements is not kept). Names and attribute values in a literal follow XML, so they are case-sensitive (unlike the rest of Visual Basic). Inside a hole the ordinary rules of Visual Basic code apply, so an expression that continues over lines needs line continuations; only directly after <%= and directly before %> may a line break stand with none.
Namespaces
A literal can declare namespaces as XML does (xmlns="…", xmlns:p="…" attributes). A file can also import them for every literal and access in it: Imports <xmlns:db="http://example.com/db"> (and Imports <xmlns="…"> for the default namespace); the project can import prefixes too. GetXmlNamespace(db) gives the XNamespace of an imported prefix (with no argument, the default namespace).
XML member access
Dim items = doc.<db:root>.<item> ' child elements
Dim kind = items.First().@kind ' an attribute
Dim all = doc...<item> ' descendants at any depth
Dim text = items.First().Value
Dim id = doc.<db:root>.@id
x.<name>– the child elements callednameof an element (or of each element of a sequence), anIEnumerable(Of XElement); a prefix may be used,x.<db:item>.x.@name– the value of the attribute as a string (Nothingif absent);x.@<db:name>names a namespace.x...<name>– the descendants calledname..Valueand the indexerx.<name>(0)read a text or pick one element, andx.<name>.Valuetakes the first.
Query expressions (LINQ) work on these sequences, so a query can read and build XML in the same expression.
Not described
Known, not yet covered
- Reference: the specification’s rules for white-space handling in content, name resolution of prefixes (including the imports of the whole project), the exact types an embedded expression may have and the translation into
System.Xml.Linqcalls are described only in outline. - Viewer: an XML literal starts when a
<followed by a name,?,!--,![CDATA[or%=stands where an expression can start (not after a value); text inside the literal is left uncoloured, and an element that is never closed colours the rest of the file as XML.
See also
- Lexical structure – the rules for ordinary code
- File structure and options –
Imports <xmlns…>