14 Mar 2010

Čtení XML pomocí třídy XDocument a ignorování vložených HTML tagů

Dnes jsem zapracoval na jednoduchém vylepšení své homepage - popisy, odkazy na obrázky, atd. jednotlivých projektů a jejich anglické a české verze jsou načítány z XML souboru. Během práce na této změně jsem opět narazil na jednu maličkou nepříjemnost, která souvisí s třídou XDocument - pokud mám nějaký text například uvnitř elementu "Text" a tento text obsahuje nějaké HTML značky, ať už je to a, b nebo div, tak se tyto značky nezobrazí/neaplikují.

Pro upřesnění malá ukázka:

  <project>
    <Image>css/projects/pdf.png</Image>
    <Url>http://chrasty.cz/down/C_threading.pdf</Url>
     <Czech>
      <Header>Překlad Threading in C# (J. Albahari)</Header>
      <Text>
        <p>
          V roce jsem 2008 jsem přeložil do českého jazyka e-book od
          Josepha Albahariho
           o vláknech v C#.
        </p>
        <p>
          Překlad jsem vydal jak ve formě
          14-ti článků na Programujte.com,
           tak i jako samostatné přibližně 80-ti stránkové PDF, které najdete ke stažení
          na mém webu, i
           na webu Josepha Albahariho.
         </p>
      </Text>
    </Czech>
...

Tříd pro práci s XML existuje celá řada a určitě existuje nějaká, ve které se dá přečtení vnitřních tagů nastavit, ale v případě třídy XDocument tomu tak není. Co tedy s tím? Můžeme použít jednu z vlastností .NET frameworku 3.5, a to konkrétně extension methods. Taková jednoduchá rozšiřující metoda, která se aplikuje na instanci třídy XElementy a umožňuje přesně to, o čem zde mluvím, může vypadat například takto:

public static string InnerXml(this XElement element)
{
    StringBuilder innerXml = new StringBuilder();

    foreach (XNode node in element.Nodes())
    {
        innerXml.Append(node.ToString());
     }
    return innerXml.ToString();
}

Již nám nic nebrání přečíst vnitřek například elementu Text rodiče Czech nějakým podobným kódem:

// proměnná "x" zde zastupuje úroveň elementu "project", viz XML kód výše
 p.Text = x.Element("Czech").Element("Text").InnerXml();