iphone - objective - url encoding swift ios
Encode NSString para XML/HTML (14)
¿Hay alguna forma de codificar HTML en una cadena (NSString) en Object-C, algo similar a Server.HtmlEncode en .NET?
¡Gracias!
Aquí está mi categoría rápida para la codificación / decodificación html:
extension String
{
static let htmlEscapedDictionary = [
"&": "&",
""" : "/"",
"'" : "''",
"9" : "''",
"’" : "''",
"–" : "''",
">" : ">",
"<" : "<"]
var escapedHtmlString : String {
var newString = "/(self)"
for (key, value) in String.htmlEscapedDictionary {
newString.replace(value, withString: key)
}
return newString
}
var unescapedHtmlString : String {
let encodedData = self.dataUsingEncoding(NSUTF8StringEncoding)!
let attributedOptions : [String: AnyObject] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding
]
let attributedString = NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil, error: nil)!
return attributedString.string
}
mutating func replace(originalString:String, withString newString:String)
{
let replacedString = self.stringByReplacingOccurrencesOfString(originalString, withString: newString, options: nil, range: nil)
self = replacedString
}
}
Supongo que un reverso de htmlEscapedDictionary podría haberse usado también en unScapedHtmlString
Nota: Como MarkBau señaló en el comentario a continuación: Dado que Swift no garantiza el orden de los diccionarios, asegúrese de reemplazar &
primero.
Aquí hay una implementación más eficiente de esta lógica de escape xml.
+ (NSString*) xmlSimpleEscape:(NSString*)unescapedStr
{
if (unescapedStr == nil || [unescapedStr length] == 0) {
return unescapedStr;
}
const int len = [unescapedStr length];
int longer = ((int) (len * 0.10));
if (longer < 5) {
longer = 5;
}
longer = len + longer;
NSMutableString *mStr = [NSMutableString stringWithCapacity:longer];
NSRange subrange;
subrange.location = 0;
subrange.length = 0;
for (int i = 0; i < len; i++) {
char c = [unescapedStr characterAtIndex:i];
NSString *replaceWithStr = nil;
if (c == ''/"'')
{
replaceWithStr = @""";
}
else if (c == ''/''')
{
replaceWithStr = @"'";
}
else if (c == ''<'')
{
replaceWithStr = @"<";
}
else if (c == ''>'')
{
replaceWithStr = @">";
}
else if (c == ''&'')
{
replaceWithStr = @"&";
}
if (replaceWithStr == nil) {
// The current character is not an XML escape character, increase subrange length
subrange.length += 1;
} else {
// The current character will be replaced, but append any pending substring first
if (subrange.length > 0) {
NSString *substring = [unescapedStr substringWithRange:subrange];
[mStr appendString:substring];
}
[mStr appendString:replaceWithStr];
subrange.location = i + 1;
subrange.length = 0;
}
}
// Got to end of unescapedStr so append any pending substring, in the
// case of no escape characters this will append the whole string.
if (subrange.length > 0) {
if (subrange.location == 0) {
[mStr appendString:unescapedStr];
} else {
NSString *substring = [unescapedStr substringWithRange:subrange];
[mStr appendString:substring];
}
}
return [NSString stringWithString:mStr];
}
+ (NSString*) formatSimpleNode:(NSString*)tagname value:(NSString*)value
{
NSAssert(tagname != nil, @"tagname is nil");
NSAssert([tagname length] > 0, @"tagname is the empty string");
if (value == nil || [value length] == 0) {
// Certain XML parsers don''t like empty nodes like "<foo/>", use "<foo />" instead
return [NSString stringWithFormat:@"<%@ />", tagname];
} else {
NSString *escapedValue = [self xmlSimpleEscape:value];
return [NSString stringWithFormat:@"<%@>%@</%@>", tagname, escapedValue, tagname];
}
}
Arreglé un proyecto de ejemplo rápido usando las respuestas de Mike y Tod here .
Hace que la codificación / descodificación sea muy simple:
NSString *html = @"<p>This /"paragraph/" contains quoted & ''single'' quoted stuff.</p>";
NSLog(@"Original String: %@", html);
NSString *escapedHTML = [html xmlSimpleEscapeString];
NSLog(@"Escaped String: %@", escapedHTML);
NSString *unescapedHTML = [escapedHTML xmlSimpleUnescapeString];
NSLog(@"Unescaped String: %@", unescapedHTML);
Consulte a continuación la respuesta:
NSString *content = global.strPrivacyPolicy;
content = [[[[[content stringByReplacingOccurrencesOfString: @"&" withString: @"&"]
stringByReplacingOccurrencesOfString:@""" withString:@"/" "]
stringByReplacingOccurrencesOfString: @"'" withString:@"''"]
stringByReplacingOccurrencesOfString: @">" withString: @">"]
stringByReplacingOccurrencesOfString: @"<" withString:@"<"];
[_webViewPrivacy loadHTMLString:content baseURL:nil];
Esta solución más fácil es crear una categoría de la siguiente manera:
Aquí está el archivo de encabezado de la categoría:
#import <Foundation/Foundation.h>
@interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
@end
Y aquí está la implementación:
#import "NSString+URLEncoding.h"
@implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*''/"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
@end
Y ahora podemos simplemente hacer esto:
NSString *raw = @"hell & brimstone + earthly/delight";
NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@",
[raw urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSLog(url);
Los créditos para esta respuesta van al siguiente sitio web:
http://madebymany.com/blog/url-encoding-an-nsstring-on-ios
He creado un codificador de URL de fuente abierta bastante poderoso que puedes encontrar here .
Lo que lo hace diferente del enfoque NSString stringByAddingPercentEscapesUsingEncoding es que respeta la porción de dominio de la URL y solo codifica la porción de ruta.
Lo he probado con más de 10.000 URL y se mantiene muy bien.
¡Buena suerte y avíseme si tiene algún problema con eso!
No estoy del todo seguro de que funcione en todos los casos, pero puede ser más fácil rodear el texto con CDATA:
<xmltag><![CDATA[some <b>long</b> <i>xml</i> text]]></xmltag>
qué es CDATA: ¿Qué significa <! [CDATA []]> en XML?
No hay un método NSString que haga eso. Tendrá que escribir su propia función que reemplaza cadenas. Es suficiente hacer los siguientes reemplazos:
- ''&'' => "& amp;"
- ''"'' =>" & quot; "
- ''/' ''= "" & # 39; "
- ''>'' => "& gt;"
- ''<'' => "& lt;"
Algo como esto debería hacer (no lo he intentado):
[[[[[myStr stringByReplacingOccurrencesOfString: @"&" withString: @"&"]
stringByReplacingOccurrencesOfString: @"/"" withString: @"""]
stringByReplacingOccurrencesOfString: @"''" withString: @"'"]
stringByReplacingOccurrencesOfString: @">" withString: @">"]
stringByReplacingOccurrencesOfString: @"<" withString: @"<"];
Si puede usar NSXMLNode (en OS X) Aquí está el truco:
NSString *string = @"test<me>"
NSXMLNode *textNode = [NSXMLNode textWithStringValue:string];
NSString *escapedString = [textNode.XMLString];
Tomé el trabajo de Mike y lo convertí en una categoría para NSMutableString y NSString
Cree una categoría para NSMutableString con:
- (NSMutableString *)xmlSimpleUnescape
{
[self replaceOccurrencesOfString:@"&" withString:@"&" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@""" withString:@"/"" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"'" withString:@"''" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"'" withString:@"''" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"’" withString:@"''" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"–" withString:@"-" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@">" withString:@">" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"<" withString:@"<" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
return self;
}
- (NSMutableString *)xmlSimpleEscape
{
[self replaceOccurrencesOfString:@"&" withString:@"&" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"/"" withString:@""" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"''" withString:@"'" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@">" withString:@">" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
[self replaceOccurrencesOfString:@"<" withString:@"<" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
return self;
}
Cree una categoría para NSString con:
- (NSString *)xmlSimpleUnescapeString
{
NSMutableString *unescapeStr = [NSMutableString stringWithString:self];
return [unescapeStr xmlSimpleUnescape];
}
- (NSString *)xmlSimpleEscapeString
{
NSMutableString *escapeStr = [NSMutableString stringWithString:self];
return [escapeStr xmlSimpleEscape];
}
* Una versión Swift 2.0 *
La versión de Objective-C es un poco más eficiente ya que realiza operaciones mutables en la cadena. Sin embargo, esta es una forma rápida de hacer escapes simples:
extension String
{
typealias SimpleToFromRepalceList = [(fromSubString:String,toSubString:String)]
// See http://.com/questions/24200888/any-way-to-replace-characters-on-swift-string
//
func simpleReplace( mapList:SimpleToFromRepalceList ) -> String
{
var string = self
for (fromStr, toStr) in mapList {
let separatedList = string.componentsSeparatedByString(fromStr)
if separatedList.count > 1 {
string = separatedList.joinWithSeparator(toStr)
}
}
return string
}
func xmlSimpleUnescape() -> String
{
let mapList : SimpleToFromRepalceList = [
("&", "&"),
(""", "/""),
("'", "''"),
("'", "''"),
("’", "''"),
("–", "-"),
(">", ">"),
("<", "<")]
return self.simpleReplace(mapList)
}
func xmlSimpleEscape() -> String
{
let mapList : SimpleToFromRepalceList = [
("&", "&"),
("/"", """),
("''", "'"),
(">", ">"),
("<", "<")]
return self.simpleReplace(mapList)
}
}
Podría haber usado las capacidades de puente NSString para escribir algo muy similar a la versión de NSString, pero decidí hacerlo más rápido.
Use el mensaje en el siguiente ejemplo:
anyStringConverted = [anyString stringByReplacingOccurrencesOfString:@"/n" withString:@"<br>"];
Esto convierte el comando ''nueva línea'' al código html correspondiente. Pero para convertir símbolos, debe escribir el número html correspondiente. Puede ver la lista completa de números html aquí en
Uso Google Toolbox para Mac (funciona en iPhone). En particular, vea las adiciones a NSString en GTMNSString+HTML.h GTMNSString+XML.h
la rutina de los samets olvidó el dígito hexadecimal. Aquí está la rutina que se me ocurrió que funciona:
- (NSString*)convertEntities:(NSString*)string
{
NSString *returnStr = nil;
if( string )
{
returnStr = [ string stringByReplacingOccurrencesOfString:@"&" withString: @"&" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@""" withString:@"/"" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"'" withString:@"''" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"9" withString:@"''" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"’" withString:@"''" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"–" withString:@"''" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@">" withString:@">" ];
returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"<" withString:@"<" ];
returnStr = [ [ NSString alloc ] initWithString:returnStr ];
}
return returnStr;
}
Para la codificación de URL :
NSString * encodedString = [originalString
stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Consulte la documentación de NSString de Apple para obtener más información.
Para la codificación HTML :
Consulte CFXMLCreateStringByEscapingEntities , que es parte de la biblioteca XML de Core Foundation, pero aún debe funcionar.