构造带SQL查询的SOAP请求时XmlDocument.LoadXml报<字符错误如何解决?
问题根因
当前采用硬拼接字符串的方式构建SOAP请求XML,当传入的动态参数(尤其是SQL语句)中包含XML保留字符(如<、>、&、引号等)时,拼接生成的字符串会不符合XML语法规范。
你遇到的Name cannot begin with the '<' character hexadecimal value 0x3c错误,直接触发原因就是SQL语句中的<(例如条件判断写法WHERE create_time < '2024-01-01')被直接拼入XML内容后,LoadXml解析器会把这个<识别为新XML标签的起始标记,当后续字符不符合XML标签命名规则时,就会抛出解析异常。
修复方案
方案1:使用XML节点API构建请求体(推荐)
完全放弃硬拼接字符串的写法,先加载不含动态内容的XML骨架,再通过节点接口给动态字段赋值,XmlDocument框架会自动对字段内容中的特殊字符做XML实体转义,从根源上避免解析错误。
修改后的参考代码:
HttpWebRequest request = CreateSOAPWebRequest(); XmlDocument SOAPReqBody = new XmlDocument(); // 加载无动态内容的XML骨架 SOAPReqBody.LoadXml(@"<?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> <Query xmlns=""http://LifaOIS.DK/OISService""> <UID></UID> <PWD></PWD> <SQL></SQL> <Meta></Meta> </Query> </soap:Body> </soap:Envelope>"); // 配置命名空间用于定位节点 XmlNamespaceManager nsManager = new XmlNamespaceManager(SOAPReqBody.NameTable); nsManager.AddNamespace("oidQuery", "http://LifaOIS.DK/OISService"); // 给节点赋值,框架自动转义特殊字符 SOAPReqBody.SelectSingleNode("//oidQuery:Query/oidQuery:UID", nsManager).InnerText = uid; SOAPReqBody.SelectSingleNode("//oidQuery:Query/oidQuery:PWD", nsManager).InnerText = pwd; SOAPReqBody.SelectSingleNode("//oidQuery:Query/oidQuery:SQL", nsManager).InnerText = sql; SOAPReqBody.SelectSingleNode("//oidQuery:Query/oidQuery:Meta", nsManager).InnerText = meta;
方案2:保留拼接逻辑时,提前对动态内容做XML转义
如果需要保留现有硬拼接的写法,必须在把动态参数拼入XML字符串前,使用C#内置的SecurityElement.Escape()方法对所有动态内容做转义,该方法会自动将特殊字符替换为XML合法的实体编码(例如<转为<,&转为&),不需要手动编写替换规则。
注意:调用该方法前需要引入using System.Security;命名空间。
参考代码片段:
// 拼接前对所有动态值做转义 string safeUid = SecurityElement.Escape(uid); string safePwd = SecurityElement.Escape(pwd); string safeSql = SecurityElement.Escape(sql); string safeMeta = SecurityElement.Escape(meta); // 用转义后的内容拼接XML SOAPReqBody.LoadXml(@"<?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> <Query xmlns=""http://LifaOIS.DK/OISService""> <UID>" + safeUid + @"</UID> <PWD>" + safePwd + @"</PWD> <SQL>" + safeSql + @"</SQL> <Meta>" + safeMeta + @"</Meta> </Query> </soap:Body> </soap:Envelope>");
注意:不要自行手写字符串替换逻辑处理特殊字符,很容易遗漏对&、引号等其他XML保留字符的转义,优先使用框架内置的转义方法。
内容的提问来源于stack exchange,提问作者compsci-78
相关产品推荐
相关产品推荐

