Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

XML literals

Alex Zimin edited this page · 3 revisions
Clone this wiki locally

Introduction

Nemerle has support for XML literals. Nemerle.Xml works on top of System.Xml.Linq. The macro creates XElement tree.

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).

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);
  }
}
Something went wrong with that request. Please try again.