Elm中如何遍历替换映射?XML转HTML实现疑问
Hey there! No worries about terminology—we all start somewhere, especially when hopping between functional languages like Haskell and Elm. Let's break down how to solve your problem, plus some better approaches to consider.
First: Fixing the Bulk Replacement
Your current replacePat function has a small signature issue (it's declared as taking Xml -> Html but expects two arguments), so let's adjust that first. Then, to apply all your replacements in sequence, we can use List.foldl—this is perfect because each replacement transforms the input string, and we can chain all those transformations together.
Here's how to adjust your code:
import Regex exposing (regex, replace, All) type alias Xml = String type alias Html = String -- Assuming your "Html" is just a string of HTML markup type alias Replacement = { pattern: String, replacement: String } type alias ReplacementMap = List Replacement -- Using type alias instead of type for simplicity replacementMap : ReplacementMap replacementMap = [ { pattern: "<head>", replacement: "<h1>" } , { pattern: "<lg>", replacement: "<ul>" } , { pattern: "<l>", replacement: "<li>" } ] -- Updated replacement function: takes a Replacement and applies it to an Xml string replacePat : Replacement -> Xml -> Html replacePat replacement xml = replace All (regex replacement.pattern) (\_ -> replacement.replacement) xml -- Apply all replacements in sequence using foldl applyReplacements : ReplacementMap -> Xml -> Html applyReplacements replacements initialXml = List.foldl replacePat initialXml replacements
To use this, just call applyReplacements replacementMap yourXmlString—it will run each replacement on the result of the previous one, giving you the transformed HTML string.
Better Approaches for the Long Run
While string replacement works for simple cases, it can be fragile (e.g., it might accidentally match text content that looks like tags). Here are two improvements to consider:
1. Precompile Regular Expressions
Right now, regex compiles the pattern every time replacePat runs. For a small replacement map this isn't a big deal, but for larger ones, precompiling will boost performance. Adjust your Replacement type to store a precompiled Regex:
import Regex exposing (Regex, regex, replace, All) type alias Replacement = { pattern: Regex, replacement: String } type alias ReplacementMap = List Replacement replacementMap : ReplacementMap replacementMap = [ { pattern: regex "<head>", replacement: "<h1>" } , { pattern: regex "<lg>", replacement: "<ul>" } , { pattern: regex "<l>", replacement: "<li>" } ] -- No need to recompile regex here anymore replacePat : Replacement -> Xml -> Html replacePat replacement xml = replace All replacement.pattern (\_ -> replacement.replacement) xml
2. Parse XML Properly (For Robustness)
If your XML gets more complex (nested tags, attributes, or text that might contain tag-like strings), string replacement will start to fail. Instead, use an XML parser to convert the string into an abstract syntax tree (AST), transform the AST, then convert it back to HTML.
Elm has a solid library called elm-xml-parser for this. Here's a quick example:
First, add the library (via elm install elm/xml-parser), then:
import XmlParser exposing (parse, Node(..), Element) import XmlParser.Pretty exposing (format) type alias Xml = String type alias Html = String -- Transform a single XML node to its HTML equivalent transformNode : Node -> Node transformNode node = case node of Element "head" attrs children -> Element "h1" attrs (List.map transformNode children) Element "lg" attrs children -> Element "ul" attrs (List.map transformNode children) Element "l" attrs children -> Element "li" attrs (List.map transformNode children) -- Pass through other elements, recursively transforming their children Element name attrs children -> Element name attrs (List.map transformNode children) Text text -> Text text Comment comment -> Comment comment -- Transform the entire XML string transformXml : Xml -> Result XmlParser.Error Html transformXml xmlString = case parse xmlString of Ok nodes -> Ok (format (List.map transformNode nodes)) Err err -> Err err
This approach is way more reliable because it understands XML structure—no more accidental matches in text content, and it handles nested tags naturally.
Hope that helps you get moving with your Elm project!
内容的提问来源于stack exchange,提问作者Jonathan

