Objective-C中NSURLSession发送SOAP请求含&字符时失效问题
解决SOAP消息含&符号导致请求失败的问题
这个问题我踩过坑!你遇到的核心问题是XML特殊字符未转义——在XML规范里,&是保留字符,直接写在元素内容里会破坏整个SOAP消息的结构,服务器解析时会抛出格式错误,自然没法正常处理请求。
为什么会这样?
XML里有5个必须转义的特殊字符,一旦直接出现在元素内容中就会导致解析失败:
&→ 必须替换为&<→ 必须替换为<>→ 必须替换为>"→ 必须替换为"'→ 必须替换为'
你的<c>U(GHB&@DG)</c>里直接用了&,XML解析器会误以为后面跟着一个合法的实体引用(比如&),但实际后面是@,自然会触发解析错误。
解决方案
1. 手动转义(临时应急)
直接把字段里的&替换成&,修改后的代码片段:
"<c>U(GHB&@DG)</c>"
但这种方法只适合临时场景,万一后续字段出现其他特殊字符(比如<),又会重复踩坑。
2. 封装通用转义方法(推荐)
写一个工具方法自动处理所有XML特殊字符,避免手动遗漏:
- (NSString *)escapeXMLSpecialCharacters:(NSString *)input { if (!input) return @""; NSMutableString *escapedString = [input mutableCopy]; // 注意:必须先替换&,因为其他转义字符本身也包含& [escapedString replaceOccurrencesOfString:@"&" withString:@"&" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)]; [escapedString replaceOccurrencesOfString:@"<" withString:@"<" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)]; [escapedString replaceOccurrencesOfString:@">" withString:@">" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)]; [escapedString replaceOccurrencesOfString:@"\"" withString:@""" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)]; [escapedString replaceOccurrencesOfString:@"'" withString:@"'" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)]; return escapedString; }
然后在构建SOAP消息时,对动态内容(尤其是可能包含特殊字符的字段)调用这个方法:
-(NSString *)createSoapMessage{ // 假设c字段是动态或可能含特殊字符的内容 NSString *cContent = @"U(GHB&@DG)"; NSString *escapedCContent = [self escapeXMLSpecialCharacters:cContent]; self.soapMessage = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" "<soap:Body>" "<F2 xmlns=\"website address\">" "<a>%@</a>" "<b>%@</b>" "<c>%@</c>" // 其他元素... "</F2>" "</soap:Body>" "</soap:Envelope>", self.aValue, self.bValue, escapedCContent]; return self.soapMessage; }
3. 进阶:用XML构建库生成SOAP消息(更安全)
如果经常处理SOAP请求,建议用专门的XML构建工具(比如系统的NSXMLDocument)来生成消息,完全避免手动拼接的问题。比如:
- (NSString *)createSoapMessageWithXMLBuilder { NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithXMLString:@"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body></soap:Body></soap:Envelope>" options:0 error:nil]; NSXMLElement *bodyElement = [xmlDoc rootElement]; NSXMLElement *f2Element = [[NSXMLElement alloc] initWithName:@"F2" xmlns:@"website address"]; // 添加a元素 NSXMLElement *aElement = [[NSXMLElement alloc] initWithName:@"a" stringValue:self.aValue]; [f2Element addChild:aElement]; // 添加b元素 NSXMLElement *bElement = [[NSXMLElement alloc] initWithName:@"b" stringValue:self.bValue]; [f2Element addChild:bElement]; // 添加c元素(自动处理转义) NSXMLElement *cElement = [[NSXMLElement alloc] initWithName:@"c" stringValue:@"U(GHB&@DG)"]; [f2Element addChild:cElement]; [bodyElement addChild:f2Element]; return [xmlDoc XMLStringWithOptions:NSXMLNodePrettyPrint]; }
这种方式会自动处理所有XML特殊字符,还能避免手动拼接时可能出现的标签闭合错误,稳定性更高。
内容的提问来源于stack exchange,提问作者sandhu
相关产品推荐
相关产品推荐

