Forum Programmation.autre langage pour écrire du XML

Posté par  (site web personnel) .
Étiquettes : aucune
0
26
mai
2006
Bonjour,

le XML c'est bien, mais il y a quand même des inconvénients parmis léquels se trouve la difficulté d'écrire du XML à la main (dans un éditeur de texte).

Oui, bien sûr, c'est pas si compliqué, sauf que cela fait pas mal de temps que je maintiens mon site web XHTML statique à la main, et c'est embêtant à la fin, on se mélange dans les < et les >, il faut écrire les noms de balise en double (une au début, l'autre à la fin) et lorsque les balises commecent a avoir une certaine longeur, tout devient complexe.

Alors ce que j'aimerais, c'est un langage plus léger qui me permette d'écrire du XML. Et si possible de faire quelques traitements (pas juste une conversion toute bête). par exemple rajouter automatiquement la date du jour ou disposer des fonctions qui vont bien pour que je puisse rajouter automatiquement (en scannant les fichiers du répertoire courant) les des liens dans des balises link du header en XHTML.

Quand je parle de plus léger, je pense à une syntaxe du style LaTeX où il suffit d'écrire :
\noeud[option=valeur,option=valeur]{...}
à la place de :
< noeud option="valeur" option="valeur" > ... < /noeud >

Voila, vous avez des idées ?
  • # langage pour écrire du XML

    Posté par  (site web personnel) . Évalué à 2.

    Euh autre solution utiliser un vrai editeur XML.
    Genre emacs + nxml (completion des balises lors de la fermeture ..)
    ou autre carrement graphique.
  • # petite création

    Posté par  (site web personnel) . Évalué à 2.

    Voila, je voulais savoir a tout hasard si cela existait ... apparament pas vraiment. Voici donc ma solution qui utilise le langage lua ( http://lua.org/ )
    #! /usr/bin/env lua
    
    -- fichier : template.lua
    
    -------------------------------------------------------------------------------
    --
    -- Copyright (C) 2006 Mildred.
    --
    -- Permission is hereby granted, free of charge, to any person obtaining a copy
    -- of this software and associated documentation files (the "Software"), to
    -- deal in the Software without restriction, including without limitation the
    -- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    -- sell copies of the Software, and to permit persons to whom the Software is
    -- furnished to do so, subject to the following conditions:
    --
    -- The above copyright notice and this permission notice shall be included in
    -- all copies or substantial portions of the Software.
    --
    -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    -- IN THE SOFTWARE.
    --
    -------------------------------------------------------------------------------
    
    --lw = require("lwbase").install()
    
    local env = { tmplchar="#", IN_TEMPLATE=true }
    setmetatable(env, {__index=_G})
    
    function env.out(...)
        env.output(...)
    end
    
    function env.finnish()
    end
    
    local process_line_buffer = {}
    local process_line_has_buffer = false
    function env.process_line(line, n)
        if process_line_has_buffer then
            if line:sub(-1) == "\\" then
                table.insert(process_line_buffer, line:sub(1, -2))
            else
                table.insert(process_line_buffer, line)
                process_line_has_buffer = false
                local b = table.concat(process_line_buffer, "\n")
                process_line_buffer = {}
                local f = assert(loadstring(b, ("template '%s' line %i to %i"):format(env.filename, n+1-#process_line_buffer, n)))
                setfenv(f, env)
                f()
            end
        elseif line:sub(1, 1) == "#" then
            if line:sub(2, 2) == "#" then
                env.out(line:sub(2).."\n")
            elseif line:sub(-1) == "\\" then
                table.insert(process_line_buffer, line:sub(2, -2))
                process_line_has_buffer = true
            else
                local f = assert(loadstring(line:sub(2), ("template '%s' line %i"):format(env.filename, n)))
                setfenv(f, env)
                f()
            end
        else
            env.out(line.."\n")
        end
    end
    
    local function main(filename)
        filename = filename or arg[0]
        env.filename = filename
        env.output = io.write
        local f = assert(io.open(filename, "r"))
        local line = f:read("*l")
        local n = 1;
        if line:sub(1, 1) == "#" then
            line = f:read("*l")
            n = n + 1
        end
        local buffer = {}
        while line and line ~= "" do
            table.insert(buffer, line);
            line = f:read("*l")
            n = n + 1
        end
        line = f:read("*l")
        buffer = table.concat(buffer, "\n")
        local func = assert(loadstring(buffer, ("template '%s' header"):format(filename)))
        setfenv(func, env)
        func()
        while line do
            env.process_line(line, n)
            line = f:read("*l")
            n = n + 1
        end
        env.finnish()
        f:close();
    end
    
    
    local lisp_any
    
    local function lisp_space(s, n)
        while s:sub(n, n):find("%s") do
            n = n + 1
        end
        return n
    end
    
    local function lisp_list(s, n)
        local o, t, ty, idf
        t = {}
        n, o, ty = lisp_any(s, n)
        idf = 1 -- tag
        --print("end", ty, n)
        while o do
            if idf then
                t[idf] = o
                idf = nil
            elseif ty == "idf" then
                if o:sub(1, 1) == ":" then
                    t[o]=true
                else
                    idf = o
                end
            elseif ty == "longstring" then
                for k, v in ipairs(o) do
                    table.insert(t, v)
                end
            else
                table.insert(t, o)
            end
            n, o, ty = lisp_any(s, n)
            --print("end", ty, n)
        end
        if type(idf)=="string" then
            table.insert(t, idf)
        end
        return n, t, "list"
    end
    
    local function lisp_idf(s, n)
        local m = s:find("[%s%)]", n)
        if not m then
            return n, nil, nil
        end
        return m, s:sub(n, m-1), "idf"
    end
    
    local function lisp_string(s, n, stop)
        local str, m
        str = {}
        stop = stop or '"'
        local continue = true
        while continue do
            m = s:find(stop, n, true)
            table.insert(str, s:sub(n, m-1))
            --print("str", "'"..s:sub(n, m-1).."'")
            if s:sub(m+1, m+1) == stop then
                --print("str", "esc")
                table.insert(str, stop)
                n = m + 2
            else
                n = m + 1
                continue = false
            end
        end
        --print("str res", table.concat(str))
        return n+1, table.concat(str), "string"
    end
    
    local function lisp_longstring(s, n, stop, esc)
        local str, m, t
        str = {}
        t = {}
        stop = stop or '"'
        esc  = esc  or ','
        while true do
            m = s:find("[%"..stop.."%"..esc.."]", n)
            table.insert(str, s:sub(n, m-1))
            if s:sub(m, m) == esc and s:sub(m+1, m+1) == '(' then
                table.insert(t, table.concat(str))
                str = {}
                local o
                n, o = lisp_list(s, m+2)
                table.insert(t, o)
            elseif s:sub(m+1, m+1) == stop then
                table.insert(str, stop)
                n = m + 2
            else
                table.insert(t, table.concat(str))
                str = {}
                n = m + 1
                break
            end
        end
        return n, t, "longstring"
    end
    
    function lisp_any(s, n)
        local c
        n = n or 1
        --print("space", n)
        n = lisp_space(s, n)
        c = s:sub(n, n)
        if c == "(" then
            --print("list", n, "'"..s:sub(n, n).."'")
            return lisp_list(s, n+1)
        elseif c == ")" then
            --print("endlist", n, "'"..s:sub(n, n).."'")
            return n+1, nil, nil
        elseif c == '"' then
            --print("string", n)
            return lisp_string(s, n+1, '"')
        elseif c == "[" then
            --print("longstring", n)
            return lisp_longstring(s, n+1, ']')
        else
            --print("idf", n, "'"..s:sub(n, n).."'");
            return lisp_idf(s, n)
        end
    end
    
    function env.lisp(s)
        return select(2, lisp_any(s))
    end
    
    function env.makexml(tree, indent, lvl)
        lvl = lvl or 0
        local nl, tab = "", ""
        local inc_level = 0
        if indent then
            assert(type(indent)=="table", "2nd parameter must be a table")
            indent.tab = indent.tab or "\t"
            indent.nl = indent.nl or "\n"
            if not indent.disable then
                nl  = indent.nl
                tab = indent.tab
                inc_level = 1
            end
        else
            indent = {tab="", nl=""}
        end
        if type(tree) == "string" then
            return (tab:rep(lvl)..tree:gsub("&", "&"):gsub("<", "<"):gsub(">", ">")..nl)
        else
            local tagname = table.remove(tree, 1)
            local tag = {tab:rep(lvl), "<", tagname}
            local old_indent_disable = indent.disable
            for k, v in pairs(tree) do
                if k == "indent:" and (v == "false" or v == "0") or k==":inline" then
                    indent.disable=true
                    nl  = ""
                    tab = ""
                    inc_level = 0
                elseif k == "indent:" and (v == "true" or v == "1") or k==":block" then
                    indent.disable=false
                    nl  = indent.nl
                    tab = indent.tab
                    inc_level = 1
                elseif type(k) == "string" then
                    table.insert(tag, " " .. k .. '="' .. env.makexml(tostring(v)) .. '"')
                end
            end
            if #tree > 0 then
                table.insert(tag, ">")
                if not indent.disable then table.insert(tag, nl) end
                for k, v in ipairs(tree) do
                    table.insert(tag, (env.makexml(v, indent, lvl+inc_level)))
                end
                if not indent.disable then table.insert(tag, tab:rep(lvl)) end
                table.insert(tag, "</" .. tagname .. ">")
            else
                table.insert(tag, "/>")
            end
            indent.disable = old_indent_disable
            if not indent.disable then table.insert(tag, indent.nl) end
            return (table.concat(tag))
        end
    end
    
    if debug.getinfo(3) == nil then
        return main(...)
    else
        return main
    end
    
    
    L'appel se fait avec une commande du type ./template.lua montemplate. Le résultat est sur la sortie standard. Un template ressemble à :
    local buffer = {}
    function out(str)
        table.insert(buffer, str)
    end
    function finnish()
        local tree = lisp(table.concat(buffer))
        output(makexml(tree, {tab="    ", nl="\n", disable=true}), "\n")
    end
    
    (html :block
        (head
            (title :inline abc))
    # out "    (body"
            (p :inline [te,(a href test abc)st])))
    
    
    pour un résultat :
    < html >
        < head >
            < title >abc< /title >
        < /head >
        < body >
            < p >te< a href="test" >abc< /a >st< /p >
        < /body >
    < /html >
    
    La syntaxe est du style lisp. Un tag commence par "(" suivi du nom du tag et se termine par ")". Les paramètres du tag peut être remplis en ajoutant entre les parenthèses le nom du paramètre (sans quotes) suivi de sa valeur. Les chaines sont entourées de quotes ou de crochets "[", "]". A l'interieur des crochets, on peut ajouter des tags en préfixant la parenthèse ouvrante par "," (comme avec la quasiquotation). Pas encore de commentaires, c'est à venir. Voila

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.