Documentacion XML a Markdown

Necesitaba documentar Open.NAT y colgarlo en la wiki del proyecto en GitHub pero no encontré nada, así que escribí un transformador XML—> Markdown que me sirviera. La verdad es que el código, si bien son solo 100 LoC, está bastante sucio pero si a alguien le sirve aquí se los dejo.

Y este es el resultado:

image

 

Con esto lo invoco:

  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         var xml = File.ReadAllText(args[0]);
  6.         var doc = XDocument.Parse(xml);
  7.         var md = doc.Root.ToMarkDown();
  8.         Console.WriteLine(md);
  9.     }
  10. }

Aquí está el código:

  1. static class XmlToMarkdown
  2. {
  3.     static IEnumerable<string> DocToMarkDown(XNode e)
  4.     {
  5.         var el = (XElement) e;
  6.         var members = el.Element(“members”).Elements(“member”);
  7.         return new[]
  8.             {
  9.                 el.Element(“assembly”).Element(“name”).Value,
  10.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“F:”)).ToMarkDown()),
  11.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“M:”)).ToMarkDown()),
  12.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“E:”)).ToMarkDown())
  13.             };
  14.     }
  15.  
  16.     internal static string ToMarkDown(this XNode e)
  17.     {
  18.         var templates = new Dictionary<string, string>
  19.             {
  20.                 {“doc”, “## {0} ##nn## Fieldsnn{1}nn## Methodsnn{2}nn## Eventsnn{3}nn”},
  21.                 {“field”, “### {0}nn{1}nn”},
  22.                 {“method”, “### {0}nn{1}nn”},
  23.                 {“event”, “### {0}nn{1}nn”},
  24.                 {“summary”, “{0}nn”},
  25.                 {“remarks”, “**remarks**nn{0}nn”},
  26.                 {“example”, “**example**nn{0}nn”},
  27.                 {“see”, “[{1}]({0})”},
  28.                 {“param”, “_{0}_: {1}” },
  29.                 {“exception”, “_{0}_: {1}nn” },
  30.                 {“returns”, “Returns: {0}nn”},
  31.                 {“none”, “”}
  32.             };
  33.         var d = new Func<string, XElement, string[]>((att, node) => new[]
  34.             {
  35.                 node.Attribute(att).Value,
  36.                 node.Nodes().ToMarkDown()
  37.             });
  38.         var methods = new Dictionary<string, Func<XElement, IEnumerable<string>>>
  39.             {
  40.                 {“doc”, DocToMarkDown},
  41.                 {“field”, x=> d(“name”, x)},
  42.                 {“method”,x=>d(“name”, x)},
  43.                 {“event”, x=>d(“name”, x)},
  44.                 {“summary”, x=> new[]{ x.Nodes().ToMarkDown() }},
  45.                 {“remarks”, x => new[]{x.Nodes().ToMarkDown()}},
  46.                 {“example”, x => new[]{x.Value.ToCodeBlock()}},
  47.                 {“see”, x=>d(“cref”,x)},
  48.                 {“param”, x => d(“name”, x) },
  49.                 {“exception”, x => d(“cref”, x) },
  50.                 {“returns”, x => new[]{x.Nodes().ToMarkDown()}},
  51.                 {“none”, x => new string[0]}
  52.             };
  53.  
  54.         string name;
  55.         if(e.NodeType== XmlNodeType.Element)
  56.         {
  57.             var el = (XElement) e;
  58.             name = el.Name.LocalName;
  59.             if (name == “member”)
  60.             {
  61.                 switch (el.Attribute(“name”).Value[0])
  62.                 {
  63.                     case ‘F’: name = “field”break;
  64.                     case ‘E’: name = “event”break;
  65.                     case ‘M’: name = “method”; break;
  66.                     default:  name = “none”;   break;
  67.                 }
  68.             }
  69.             var vals = methods[name](el).ToArray();
  70.             string str=“”;
  71.             switch (vals.Length)
  72.             {
  73.                 case 1: str= string.Format(templates[name], vals[0]);break;
  74.                 case 2: str= string.Format(templates[name], vals[0],vals[1]);break;
  75.                 case 3: str= string.Format(templates[name], vals[0],vals[1],vals[2]);break;
  76.                 case 4: str= string.Format(templates[name], vals[0], vals[1], vals[2], vals[3]);break;
  77.             }
  78.  
  79.             return str;
  80.         }
  81.  
  82.         if(e.NodeType==XmlNodeType.Text)
  83.             return Regex.Replace( ((XText)e).Value.Replace(‘n’, ‘ ‘), @”s+”, ” “);
  84.  
  85.         return “”;
  86.     }
  87.  
  88.     internal static string ToMarkDown(this IEnumerable<XNode> es)
  89.     {
  90.         return es.Aggregate(“”, (current, x) => current + x.ToMarkDown());
  91.     }
  92.  
  93.     static string ToCodeBlock(this string s)
  94.     {
  95.         var lines = s.Split(new char[] {‘n’}, StringSplitOptions.RemoveEmptyEntries);
  96.         var blank = lines[0].TakeWhile(x => x == ‘ ‘).Count() – 4;
  97.         return string.Join(“n”,lines.Select(x => new string(x.SkipWhile((y, i) => i < blank).ToArray())));
  98.     }
  99. }
Sin categoría

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *