XML literals
From Nemerle Homepage
[edit]
Introduction
Nemerle has support for XML literals. Nemerle.Xml works on top of System.Xml.Linq. The macro creates XElement tree.
[edit]
Features
1. Global namespace using DefineXmlns assembly attribute:
[assembly: DefineXmlns(ns1="some-ns")]
2. Local namespace using xmlns attribute:
xml <# <ns2:a ns2:aa="zz" xmlns:ns2="namespace-2"></ns2:a> #>;
3. Splice expressions:
- Tag names (Only XName expressions).
- Attributes. Only XAttribute expressions (for $-expressions) or IEnumerable[XAttribute] (for ..$-expressions).
- Attribute values (Any types except XAttribute). When value is null either for reference or for nullable types, the whole attribute is removed (VB behaviour).
- Tags. Only XElement expressions (for $-expressions) or IEnumerable[XElement] (for ..$-expressions). When value is null, nothing inserted in XML (XLinq behaviour).
- Text (Any type which can be converted to string with XLinq). When value is null, nothing is inserted in XML (XLinq behaviour).
4. Control flow expressions:
- foreach. Iterates over tag for each list entry:
<li $foreach (p in props)>$(p.Name) : $(p.PropertyType)</li>
The standard foreach macro is used. Most of its features are supported (pattern matching should work too)
- when. Produces tag when the condition is true:
<H2 $when (props.Length > 0)>Properties</H2>
- unless. Produces tag when the condition is false:
<H2 $unless (props.IsEmpty())>Events</H2>
5. XML correctness control (without schema) is done in compile time.
6. The XML tags can be closed without specifying name: </> (Like in VB).
[edit]
Example
using Nemerle.Collections; using Nemerle.Xml; using System; using System.Console; using System.Xml.Linq; [assembly: DefineXmlns(ns1="some-ns")] class TestClass { public Prop1 : int { get; set; } public Prop2 : string { get; set; } } module Program { Main() : void { def makeClassInfoPage(cls : Type) : void { def props = cls.GetProperties(); def events = cls.GetEvents(); def title = $"The class <$(cls.Name)>"; def html = xml <# <html> <head> <title>$title</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" href="http://rsdn.ru/css/article.css" type="text/css" /> </head> <body marginwidth="20" marginheight="20"> <H1>$title</H1> <H2 $unless (props.IsEmpty())>Properties</H2> <ol $unless (props.IsEmpty())> <li $foreach (p in props)>$(p.Name) : $(p.PropertyType)</li> </ol> <H2 $unless (events.IsEmpty())>Events</H2> <ol $unless (events.IsEmpty())> <li $foreach (e in events)>$(e.Name) : $(e.EventHandlerType)</li> </ol> </body> </html> #>; def path = IO.Path.ChangeExtension(IO.Path.GetTempFileName(), "html"); IO.File.WriteAllText(path, html.ToString()); _ = Diagnostics.Process.Start(path); } makeClassInfoPage(typeof(XAttribute)); makeClassInfoPage(typeof(TestClass)); def z : int? = 42; def a = [XAttribute("LANG", "enu"), XAttribute("xx", "yy")]; def e1 = xml <# <x /> #>; def elems = [XElement("w"), e1]; def res1 = xml <# <e a="a" ns1:a=$z ..$a>Text $e1<ns2:a ns2:aa="zz" xmlns:ns2="namespace-2"></ns2:a> abc ..$elems</e> #>; WriteLine(res1); def name = XName.Get("dyn"); def res2 = xml <# <ns2:a xmlns:ns2="namespace-2"><$name $when (z.HasValue) ns1:a="123"/></> #>; WriteLine(res2); } }