2016-06-09 15 views
1

Ich möchte ein gültiges HTML mit nicht sehr tiefer Verschachtelungsebene in ein anderes HTML mit eingeschränkteren Regeln umwandeln.HTML in Haskell transformieren

Nur die folgenden Tags werden in dem resultierenden HTML unterstützt:

<b></b>, <strong></strong>, <i></i>, <em></em>, <a 
href="URL"></a>, <code></code>, <pre></pre> 

Nested-Tags werden überhaupt nicht erlaubt.

Für den Rest der Tags und deren Kombinationen muss ich eine Art von Regeln erstellen, wie mit jedem umzugehen. So habe ich so etwas wie konvertieren:

<p>text</p> in einfachen String text mit Zeilenumbruch,

<b>text <a href="url">link</a> text</b> in text link text

<a href="url">text<code> code here</code></a> in <a href="url">text code here</a> weil <code> innen <a> verschachtelt ist und so weiter.

Zum Beispiel HTML (Zeilenumbrüche sind nur für Bequemlichkeit):

<p>long paragraph <a href="url">link</a> </p> 
<p>another text <pre><code>my code block</code></pre> the rest of description</p> 
<p><code>inline monospaced text with <a href="url">link</a></code></p> 

in umgewandelt werden soll:

long paragraph <a href="url">link</a> 

another text <code>my code block</code> the rest of description 

<code>inline monospaced text with link</code> 

Jeder Vorschlag auf dem Weg, das zu lösen?

Antwort

2

Nach einigen Untersuchungen habe ich meiner Meinung nach ziemlich elegante Lösung gefunden. Es basiert auf tagsoup Bibliothek. Die Bibliothek verfügt über Text.HTML.TagSoup.Tree Modul, mit dem HTML in Baumstruktur analysiert werden kann.

Es enthält auch transformTree Funktion, die Transformation ziemlich trivial. Dokumentation dieser Funktion sagt:

Diese Operation basiert auf der Uniplate-Transformationsfunktion. Bei einer Liste von Bäumen wendet es die Funktion auf jeden Baum in einer Bottom-Up-Weise an.

Sie können über Uniplate mehr here lesen.

Dies ist der Code, den ich war zufrieden mit:

import Text.HTML.TagSoup 
import Text.HTML.TagSoup.Tree 

convert = transformTree f 
    where 
     f (TagLeaf (TagOpen "br" _)) = [TagLeaf (TagText "\n")] -- line breaks 
     f (TagLeaf (TagOpen _ _)) = [] -- ignore all tags without closing pairs 
     f (TagBranch "a" attrs inner) = tagExtr "a" attrs inner -- keeps href for <a> 
     f (TagBranch "p" _ inner) = inner ++ [(TagLeaf (TagText "\n"))] 
     f (TagBranch "pre" _ [TagBranch "code" _ inner]) = tagExtr "pre" [] inner -- <pre><code> -> <code> 
     f (TagBranch tag _ inner) = if tag `elem` allowedTags then tagExtr tag [] inner else inner 
     f x = [x] 

tagExtr tag attrs inner = [TagBranch tag attrs [(extractFrom inner)]] 

allowedTags = ["b", "i", "a", "code", "a", "pre", "em", "strong"] 

extractFrom x = TagLeaf $ TagText $ (innerText . flattenTree) x 
+2

Vielen Dank für uns zu zeigen, was Sie gefunden. – ErikR