-
Notifications
You must be signed in to change notification settings - Fork 90
XML literals
Alex Zimin edited this page Jul 11, 2011
·
3 revisions
Nemerle has support for XML literals. Nemerle.Xml works on top of System.Xml.Linq. The macro creates XElement tree.
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).
- 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).
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);
}
}