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 *