2010-07-26 16 views
8

tengo una cadena de Erlang que puede contener caracteres como & "< y así sucesivamente:¿Cómo puedo codificar XML una cadena en Erlang?

1> Unenc = "string & \"stuff\" <". 
ok 

¿Hay una función Erlang en alguna parte que analiza la cadena y codifica todas las entidades HTML necesario/XML, tales como:

2> Enc = xmlencode(Unenc). 
"string &amp; &quot;stuff&quot; &lt;". 

?

Mi caso de uso es para las cadenas relativamente cortas, que provienen de la entrada del usuario. las cadenas de salida de la función xmlencode será el contenido de XML en tributos:

<company name="Acme &amp; C." currency="&euro;" /> 

El XML final se enviará a través del cable de forma adecuada.

+0

Solo para asegurarse de que sabe esto: URL Encoding! = XML Encoding – ZeissS

Respuesta

2

Si sus necesidades son simples, puede hacer esto con un mapa sobre los caracteres en la cadena.

quote($<) -> "&lt;"; 
quote($>) -> "&gt;"; 
quote($&) -> "&amp;"; 
quote($") -> "&quot;"; 
quote(C) -> C. 

allí tendría que hacer

1> Raw = "string & \"stuff\" <". 
2> Quoted = lists:map(fun quote/1, Raw). 

Pero Quoted no habría una lista plana, lo que es aún válido si se va a enviar a un archivo o como una respuesta HTTP. Es decir. ver las listas de Erlang.

En versiones más recientes de Erlang, ahora hay funciones de decodificación-decodificación para multibyte utf8 para representaciones de ancho de bytes/punto de código, consulte erlang unicode module.


comentarios formateado, para hacer ejemplos de código se destacan:

Ettore: Eso es algo de lo que estoy haciendo, aunque tengo que admitir caracteres de varios bytes. Aquí está mi código:

xmlencode([], Acc) -> Acc; 
xmlencode([$<|T], Acc) -> xmlencode(T, AcC++ "&lt;"); % euro symbol 
xmlencode([226,130,172|T], Acc) -> xmlencode(T, AcC++ "&#8364;"); 
xmlencode([OneChar|T], Acc) -> xmlencode(T, lists:flatten([Acc,OneChar])). 

Aunque preferiría no reinventar la rueda si es posible.

dsmith: La cadena que está utilizando normalmente sería una lista de puntos de código Unicode (es decir, una lista de números), por lo que cualquier codificación de bytes dada es irrelevante. Solo deberías preocuparte por codificaciones específicas si trabajas directamente con binarios.

Para aclarar, el punto de código Unicode para el símbolo del euro (decimal 8364) sería un elemento único en su lista. Así que usted acaba de hacer esto:

xmlencode([8364|T], Acc) -> xmlencode(T, AcC++ "&#8364;"); 
+0

Eso es lo que estoy haciendo, aunque tengo que admitir caracteres multibyte. Aquí está mi código: xmlencode ([], Acc) -> Acc; xmlencode ([$ <|T], Acc) -> xmlencode (T, AcC++ "< "); % símbolo del euro xmlencode ([226130172 | T], Acc) -> xmlencode (T, AcC++" €"); xmlencode ([OneChar | T], Acc) -> xmlencode (T, listas: aplanar ([Acc, OneChar])). Aunque preferiría no reinventar la rueda si es posible. – ettore

+0

@ettore - La cadena que lo que está utilizando normalmente sería una lista de puntos de código Unicode (es decir, una lista de números), por lo que cualquier codificación de bytes dada es irrelevante. Solo necesita preocuparse por codificaciones específicas si está trabajando directamente con los binarios. – dsmith

+0

Para aclarar , el punto de código Unicode para el símbolo del euro (decimal 8364) sería un elemento único en su lista. Entonces simplemente haría esto: xmlencode ([8364 | T], Acc) -> xmlencode (T, AcC++ "€"); – dsmith

4

Hay una función en la distribución de Erlang que se escapa entre paréntesis angulares y los símbolos de unión pero no está documentado por lo que probablemente no es el mejor que confiar en él:

1> xmerl_lib:export_text("string & \"stuff\" <"). 
"string &amp; \"stuff\" &lt;" 

Si quiere construir/codificar estructuras XML (en lugar de codificar solo una cadena), entonces la API xmerl sería una buena opción, por ej.

2> xmerl:export_simple([{foo, [], ["string & \"stuff\" <"]}], xmerl_xml). 
["<?xml version=\"1.0\"?>", 
[[["<","foo",">"], 
    ["string &amp; \"stuff\" &lt;"], 
    ["</","foo",">"]]]] 
+0

Lo intenté, pero desafortunadamente tiene muy poco soporte junto a <> &. Estoy buscando una función que pueda codificar una amplia variedad de caracteres dentro de una codificación determinada: letras acentuadas, derechos de autor, monedas (por ejemplo: euro €), etc. – ettore

+1

¿Desea una función como htmlentities de PHP, no htmlspecialchars de PHP? Me gustaría portarlo de algo como http://htmlentities.rubyforge.org/ o http://phpjs.org/functions/htmlentities –

1

No conozco ninguno de los paquetes OTP incluidos.Sin embargo, el módulo mochiweb_html de Mochiweb tiene una función de escape: mochiweb_html.erl maneja listas, binarios y átomos.

Y para la codificación de URL, compruebe el módulo mochiweb_util: mochiweb_util.erl con su función urlescape.

Puede usar cualquiera de esas bibliotecas para obtener lo que necesita.

+0

Gracias, eché un vistazo a mochiweb_html: escapar, sin embargo, parece que escapa solo las entidades predefinidas. Cualquier otro carácter, sin importar el contenido de bytes que puedan tener, parece dejarse como está, a menos que me haya olvidado de algo: escape_attr ([C | Rest], Acc) -> escape_attr (Rest, [C | Acc]). Con el fin de crear atributos XML bien formados, esto es suficiente, supongo. – ettore

+0

Es suficiente para crear xml bien formado. Sin embargo, puede o no ser suficiente para apoyar sus necesidades de escape. Si tiene necesidades de escape específicas de la aplicación, puede necesitar implementarlas usted mismo. –

Cuestiones relacionadas