2010-12-16 16 views
9

Eché un vistazo a string escape into XML y me pareció muy útil.cadena de escape en XML-Attribute

Me gustaría hacer algo similar: escapar de una cadena que se utilizará en un atributo XML.

La cadena puede contener \ r \ n. La clase XmlWriter produce algo así como \ r \ n -> & #xD; & #xA;

La solución que estoy usando actualmente incluye el XmlWriter y un StringBuilder y es bastante fea.

¿Alguna pista?

Edit1:
siento decepcionar Larsh, comprar mi primer acercamiento fue

public static string XmlEscapeAttribute(string unescaped) 
{ 
    XmlDocument doc = new XmlDocument(); 
    XmlAttribute attr= doc.CreateAttribute("attr"); 
    attr.InnerText = unescaped; 
    return attr.InnerXml; 
} 

No funciona. XmlEscapeAttribute("Foo\r\nBar") dará como resultado "Foo\r\nBar"

Utilicé el reflector .NET, para descubrir cómo el XmlTextWriter escapa de los atributos. Se utiliza la clase XmlTextEncoder que es interno ...

Mi método lokks estoy actualmente USIG así:

public static string XmlEscapeAttribute(string unescaped) 
{ 
    if (String.IsNullOrEmpty(unescaped)) return unescaped; 

    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.OmitXmlDeclaration = true; 
    StringBuilder sb = new StringBuilder(); 
    XmlWriter writer = XmlWriter.Create(sb, settings); 

    writer.WriteStartElement("a"); 
    writer.WriteAttributeString("a", unescaped); 
    writer.WriteEndElement(); 
    writer.Flush(); 
    sb.Length -= "\" />".Length; 
    sb.Remove(0, "<a a=\"".Length); 

    return sb.ToString(); 
} 

Es feo y probablemente lento, pero funciona: XmlEscapeAttribute("Foo\r\nBar") dará lugar a "Foo&#xD;&#xA;Bar"

Edit2:

SecurityElement.Escape(unescaped); 

no funciona bien.

Edit3 (final):

Utilizando todos los comentarios muy útiles de Lars, mi implementación final es el siguiente:

Nota: la .Replace("\r", "&#xD;").Replace("\n", "&#xA;"); no es necesaria para XML válido. ¡Es una medida cosmética solamente!

public static string XmlEscapeAttribute(string unescaped) 
    { 

     XmlDocument doc = new XmlDocument(); 
     XmlAttribute attr= doc.CreateAttribute("attr"); 
     attr.InnerText = unescaped; 
     // The Replace is *not* required! 
     return attr.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;"); 
    } 

Como resulta que esto es XML válido y será analizado por cualquier estándar compatible con XML parser:

<response message="Thank you, 
LarsH!" /> 
+1

Podría modificar la técnica en la respuesta se ha vinculado a arriba, de manera que se crea un nodo de atributo, mete la cadena en innerText del nodo, y extrae su InnerXml? ¿Qué sucede si simplemente cambias CreateElement() a CreateAttribute()? – LarsH

+0

También debe asegurarse de evitar comillas dobles. –

Respuesta

7

Modificación de la solución que se hace referencia, ¿qué hay de

public static string XmlEscape(string unescaped) 
{ 
    XmlDocument doc = new XmlDocument(); 
    var node = doc.CreateAttribute("foo"); 
    node.InnerText = unescaped; 
    return node.InnerXml; 
} 

Todos Lo que hice fue cambiar CreateElement() a CreateAttribute(). El tipo de nodo de atributo tiene propiedades de InnerText e InnerXml.

No tengo el entorno para probar esto, pero me gustaría saber si funciona.

Actualización: O más simplemente, use SecurityElement.Escape() según lo sugerido en otra respuesta a la pregunta que enlazó. Esto escapará de las comillas, por lo que es adecuado para usar para texto de atributo.

Actualización 2: Tenga en cuenta que retornos de carro y avances de línea no necesita ser escapado en un valor de atributo, para que el XML para estar bien formados. Si desea que se escapen por otros motivos, puede hacerlo usando String.replace(), p.

SecurityElement.Escape(unescaped).Replace("\r", "&#xD;").Replace("\n", "&#xA;"); 

o

return node.InnerXml.Replace("\r", "&#xD;").Replace("\n", "&#xA;"); 
+0

Lo siento, pero tampoco funciona. (ver edición) –

+0

@Simon, ¿llevarías tu auto al mecánico y solo dirías que "no funciona"? ¿Qué hay de especificar lo que realmente sucedió? y cómo difiere de lo que esperabas. De lo contrario, nos deja adivinar cuál es el problema. – LarsH

+0

"<" está escapado "\ r" y "\ n" no son - como expliqué en mi edición en mi pregunta original. –

-1

si puede ser de alguna ayuda, en varios idiomas, se utiliza createCDATASection para evitar todos los caracteres especiales XML.

Se añade algo como esto:

<tag><![CDATA[ <somecontent/> ]]></tag> 
+2

@Matthias, el OP preguntó cómo escapar de una cadena que se utilizará * en un atributo *. ¿Puedes poner una sección CDATA en un valor de atributo? – LarsH

+1

Debo leer la pregunta antes de responder ...CDATA no se puede usar en un valor de atributo. –

Cuestiones relacionadas