You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C中NSURLSession发送SOAP请求含&字符时失效问题

解决SOAP消息含&符号导致请求失败的问题

这个问题我踩过坑!你遇到的核心问题是XML特殊字符未转义——在XML规范里,&是保留字符,直接写在元素内容里会破坏整个SOAP消息的结构,服务器解析时会抛出格式错误,自然没法正常处理请求。

为什么会这样?

XML里有5个必须转义的特殊字符,一旦直接出现在元素内容中就会导致解析失败:

  • & → 必须替换为 &
  • < → 必须替换为 &lt;
  • > → 必须替换为 &gt;
  • " → 必须替换为 &quot;
  • ' → 必须替换为 &apos;

你的<c>U(GHB&@DG)</c>里直接用了&,XML解析器会误以为后面跟着一个合法的实体引用(比如&amp;),但实际后面是@,自然会触发解析错误。

解决方案

1. 手动转义(临时应急)

直接把字段里的&替换成&amp;,修改后的代码片段:

"<c>U(GHB&amp;@DG)</c>"

但这种方法只适合临时场景,万一后续字段出现其他特殊字符(比如<),又会重复踩坑。

2. 封装通用转义方法(推荐)

写一个工具方法自动处理所有XML特殊字符,避免手动遗漏:

- (NSString *)escapeXMLSpecialCharacters:(NSString *)input {
    if (!input) return @"";
    
    NSMutableString *escapedString = [input mutableCopy];
    // 注意:必须先替换&,因为其他转义字符本身也包含&
    [escapedString replaceOccurrencesOfString:@"&" withString:@"&amp;" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)];
    [escapedString replaceOccurrencesOfString:@"<" withString:@"&lt;" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)];
    [escapedString replaceOccurrencesOfString:@">" withString:@"&gt;" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)];
    [escapedString replaceOccurrencesOfString:@"\"" withString:@"&quot;" options:NSLiteralSearch range:NSMakeRange(0, escapedString.length)];
    [escapedString replaceOccurrencesOfString:@"'" withString:@"&apos;" 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:23:11