C# XmlDocument.LoadXML根级别数据无效:移除XML隐藏起始字符
问题场景
调用外部API返回的XML字符串被外层双引号包裹,且字符串开头存在隐藏字符,无法直接通过XmlDocument.LoadXml()正常解析,始终抛出"根级别数据无效"的异常。
返回的原始XML字符串(日志显示):
"<?xml version='1.0' encoding='UTF-8'?> <PDB> <TRANSACTION_TYPE> <TYPE>ERROR</TYPE> </TRANSACTION_TYPE> <ERROR> <DESCRIPTION>Bad Input. Please check.</DESCRIPTION> </ERROR> </PDB>"
环境与尝试结果
基于.NET Framework 4.5.2的C#开发,尝试过多种针对XML解析"根级别数据无效"问题的常见解决方案均无效。执行string responseData = reader.ReadToEnd();获取到上述字符串后,调用XmlDocument.LoadXML()抛出以下异常:
System.Xml.XmlException: Data at the root level is invalid. Line 1, position 201.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
原尝试代码:
using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse()) { if (response.StatusCode == HttpStatusCode.Created) { using (var respStream = response.GetResponseStream()) { using (var reader = new System.IO.StreamReader(respStream, true)) { string responseData = reader.ReadToEnd(); if (responseData.Contains(@"<TYPE>ERROR</TYPE>")) { string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); if (responseData.StartsWith(_byteOrderMarkUtf8, StringComparison.Ordinal)) { log.DebugFormat("responseData starts with HIDDEN : {0}", _byteOrderMarkUtf8); // 日志中显示为?字符 // 尝试删除首字符时会删掉外层双引号,无法只移除隐藏字符 } XmlDocument doc = new XmlDocument(); doc.LoadXml(responseData); } } } } }
有效解决方案
通过截取XML根节点<PDB>到</PDB>之间的核心内容,直接传入LoadXml()进行解析,避开外层引号与开头隐藏字符的干扰:
using (var reader = new System.IO.StreamReader(respStream, true)) { string responseData = reader.ReadToEnd(); if (responseData.Contains(@"<TYPE>ERROR</TYPE>")) { int pFrom = responseData.IndexOf("<PDB>"); int pTo = responseData.LastIndexOf("</PDB>"); string subresponseData = responseData.Substring(pFrom, (pTo - pFrom) + "</PDB>".Length); XmlDocument doc = new XmlDocument(); doc.LoadXml(subresponseData); } }
内容的提问来源于stack exchange,提问作者Ziggler

