質問

Objective-Cの文字列(NSString)をHTMLエンコードする方法はありますか?

役に立ちましたか?

解決

それを行うNSStringメソッドはありません。文字列の置換を行う独自の関数を作成する必要があります。次の置換を行うだけで十分です。

  • '<!> amp;' = <!> gt; <!> quot; <!> amp; amp; <!> quot;
  • '<!> quot;' = <!> gt; <!> quot; <!> amp; quot; <!> quot;
  • '\' '= <!> gt; <!> quot; <!> amp;#39; <!> quot;
  • '<!> gt;' = <!> gt; <!> quot; <!> amp; gt; <!> quot;
  • '<!> lt;' = <!> gt; <!> quot; <!> amp; lt; <!> quot;

次のようなことができるはずです(試していません):

[[[[[myStr stringByReplacingOccurrencesOfString: @"&" withString: @"&amp;"]
 stringByReplacingOccurrencesOfString: @"\"" withString: @"&quot;"]
 stringByReplacingOccurrencesOfString: @"'" withString: @"&#39;"]
 stringByReplacingOccurrencesOfString: @">" withString: @"&gt;"]
 stringByReplacingOccurrencesOfString: @"<" withString: @"&lt;"];

他のヒント

マイクの仕事を取り上げて、NSMutableStringとNSStringのカテゴリに変えました

NSMutableStringのカテゴリを次のもので作成します:

- (NSMutableString *)xmlSimpleUnescape
{
    [self replaceOccurrencesOfString:@"&amp;"  withString:@"&"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&quot;" withString:@"\"" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&#x27;" withString:@"'"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&#39;"  withString:@"'"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&#x92;" withString:@"'"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&#x96;" withString:@"-"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&gt;"   withString:@">"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"&lt;"   withString:@"<"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];

    return self;
}

- (NSMutableString *)xmlSimpleEscape
{
    [self replaceOccurrencesOfString:@"&"  withString:@"&amp;"  options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"\"" withString:@"&quot;" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"'"  withString:@"&#x27;" options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@">"  withString:@"&gt;"   options:NSLiteralSearch range:NSMakeRange(0, [self length])];
    [self replaceOccurrencesOfString:@"<"  withString:@"&lt;"   options:NSLiteralSearch range:NSMakeRange(0, [self length])];

    return self;
}

次でNSStringのカテゴリを作成します:

- (NSString *)xmlSimpleUnescapeString
{
    NSMutableString *unescapeStr = [NSMutableString stringWithString:self];

    return [unescapeStr xmlSimpleUnescape];
}


- (NSString *)xmlSimpleEscapeString
{
    NSMutableString *escapeStr = [NSMutableString stringWithString:self];

    return [escapeStr xmlSimpleEscape];
}

* Swift 2.0バージョン*

Objective-Cバージョンは、文字列に対して可変操作を行うため、もう少し効率的です。ただし、これは簡単なエスケープを行うための迅速な方法です。

extension String
{
    typealias SimpleToFromRepalceList = [(fromSubString:String,toSubString:String)]

    // See http://stackoverflow.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 = [
            ("&amp;",  "&"),
            ("&quot;", "\""),
            ("&#x27;", "'"),
            ("&#39;",  "'"),
            ("&#x92;", "'"),
            ("&#x96;", "-"),
            ("&gt;",   ">"),
            ("&lt;",   "<")]

        return self.simpleReplace(mapList)
    }

    func xmlSimpleEscape() -> String
    {
        let mapList : SimpleToFromRepalceList = [
            ("&",  "&amp;"),
            ("\"", "&quot;"),
            ("'",  "&#x27;"),
            (">",  "&gt;"),
            ("<",  "&lt;")]

        return self.simpleReplace(mapList)
    }
}
NS

Google Toolbox for Mac (iPhoneで動作)を使用しています。特に、 GTMNSString + HTML.h および GTMNSString + XML.h

URLエンコードの場合

NSString * encodedString = [originalString
      stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];

詳細については、 AppleのNSStringドキュメントを参照してください。

>

HTMLエンコーディングの場合

Core Foundation XMLライブラリの一部である CFXMLCreateStringByEscapingEntities をご覧ください。 、しかし、まだトリックを行う必要があります。

sametsのルーチンは16進数を忘れていました。これが私が思いついたルーチンです:

- (NSString*)convertEntities:(NSString*)string
{

NSString    *returnStr = nil;

    if( string )
    {
        returnStr = [ string stringByReplacingOccurrencesOfString:@"&amp;" withString: @"&"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&#x27;" withString:@"'"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&#x39;" withString:@"'"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&#x92;" withString:@"'"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&#x96;" withString:@"'"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"  ];

        returnStr = [ returnStr stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"  ];

        returnStr = [ [ NSString alloc ] initWithString:returnStr ];
    }

    return returnStr;
}

この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 = @"&quot;";
    }
    else if (c == '\'')
    {
      replaceWithStr = @"&#x27;";
    }
    else if (c == '<')
    {
      replaceWithStr = @"&lt;";
    }
    else if (c == '>')
    {
      replaceWithStr = @"&gt;";
    }
    else if (c == '&')
    {
      replaceWithStr = @"&amp;";
    }

    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];    
  }
}

NSXMLNodeを使用できる場合(OS Xで)ここにトリックがあります:

NSString *string = @"test<me>"
NSXMLNode *textNode = [NSXMLNode textWithStringValue:string];
NSString *escapedString = [textNode.XMLString];

これは、htmlエンコード/デコードの私の迅速なカテゴリです:

extension String
{
    static let htmlEscapedDictionary = [
        "&amp;": "&",
        "&quot;" : "\"",
        "&#x27;" : "'",
        "&#x39;" : "'",
        "&#x92;" : "'",
        "&#x96;" : "'",
        "&gt;" : ">",
        "&lt;" : "<"]

    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
    }
}

htmlEscapedDictionaryの逆もunescapedHtmlStringで使用できたと思います

注:以下のコメントでMarkBauが指摘したように、Swiftは辞書の順序を保証しないため、必ず&を置き換えてください。

すべての場合に機能するかどうかは完全にはわかりませんが、テキストをCDATAで囲む方が簡単かもしれません:

<xmltag><![CDATA[some <b>long</b> <i>xml</i> text]]></xmltag>

CDATAとは: 何が<!> lt;![CDATA []] <!> gt; XMLではどうですか?

マイクとトッドの回答こちらを使用して、簡単なサンプルプロジェクトをまとめました。

エンコード/非エンコードを完全にシンプルにします:

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);

Swift 4

extension String {
    var xmlEscaped: String {
        return replacingOccurrences(of: "&", with: "&amp;")
            .replacingOccurrences(of: "\"", with: "&quot;")
            .replacingOccurrences(of: "'", with: "&#39;")
            .replacingOccurrences(of: ">", with: "&gt;")
            .replacingOccurrences(of: "<", with: "&lt;")
    }
}

この最も簡単な解決策は、次のようにカテゴリを作成することです:

Here <!>#8217; s the category <!>#8217; s header file:

#import <Foundation/Foundation.h>
@interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
@end

そしてここ<!>#8217; sの実装:

#import "NSString+URLEncoding.h"
@implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
               (CFStringRef)self,
               NULL,
               (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
               CFStringConvertNSStringEncodingToEncoding(encoding));
}
@end

そして、これで簡単にできるようになりました:

NSString *raw = @"hell & brimstone + earthly/delight";
NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@",
            [raw urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSLog(url);

この回答のクレジットは、以下のWebサイトに表示されます:-

http://madebymany.com/blog/url-encoding-an-nsstring-on-ios

回答の下を参照:

NSString *content = global.strPrivacyPolicy;
content =  [[[[[content stringByReplacingOccurrencesOfString: @"&amp;" withString: @"&"]
stringByReplacingOccurrencesOfString:@"&quot;"  withString:@"\" "]
stringByReplacingOccurrencesOfString: @"&#39;"  withString:@"'"]
stringByReplacingOccurrencesOfString: @"&gt;" withString: @">"]
stringByReplacingOccurrencesOfString:  @"&lt;" withString:@"<"];
[_webViewPrivacy loadHTMLString:content baseURL:nil];

次の例のメッセージを使用します。

anyStringConverted = [anyString stringByReplacingOccurrencesOfString:@"\n" withString:@"<br>"]; 

これは、「改行」コマンドを対応するhtmlコードに変換します。ただし、シンボルを変換するには、対応するhtml番号を記述する必要があります。 ここでhtml番号の完全なリストを見ることができます

http://www.ascii.cl/htmlcodes.htm

組み込み関数のみ(手動解析ではない)を使用し、すべてのケースをカバーする唯一の方法を見つけました。 Foundationに加えてAppKit / UIKitが必要です。これはSwiftですが、簡単にObjective-Cにすることができます:

func encodedForHTML() -> String {

    // make a plain attributed string and then use its HTML write functionality
    let attrStr = NSAttributedString(string: self)

    // by default, the document outputs a whole HTML element
    // warning: if default apple implementation changes, this may need to be tweaked
    let options: [NSAttributedString.DocumentAttributeKey: Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .excludedElements: [
                "html",
                "head",
                "meta",
                "title",
                "style",
                "p",
                "body",
                "font",
                "span"
            ]
    ]

    // generate data and turn into string
    let data = try! attrStr.data(from: NSRange(location: 0, length: attrStr.length), documentAttributes: options)
    let str = String(data: data, encoding: .utf8)!

    // remove <?xml line
    return str.components(separatedBy: .newlines).dropFirst().first!
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top