从 XML 声明片段获取 XML 编码:部分内容解析不支持 XmlDeclaration
Posted
技术标签:
【中文标题】从 XML 声明片段获取 XML 编码:部分内容解析不支持 XmlDeclaration【英文标题】:Obtaining the XML encoding from an XML declaration fragment: XmlDeclaration is not supported for partial content parsing 【发布时间】:2016-03-21 11:28:27 【问题描述】:我正在编写一些代码来读取包含 XML 声明的 XML 片段,例如<?xml version="1.0" encoding="utf-8"?>
并解析编码。从MSDN,我应该可以这样做:
var nt = new NameTable();
var mgr = new XmlNamespaceManager(nt);
var context = new XmlParserContext(null, mgr, null, XmlSpace.None);
var reader = new System.Xml.XmlTextReader(@"<?xml version=""1.0"" encoding=""UTF-8""?>",
System.Xml.XmlNodeType.XmlDeclaration, context);
但是,我在调用 System.Xml.XmlTextReader
构造函数时收到了一个 System.Xml.XmlException
并带有一条错误消息:
部分内容不支持 XmlNodeType XmlDeclaration 解析。
我已经在引号中搜索了这个错误 - 找到的结果恰好为零(编辑:现在有一个结果:这篇文章) - 并且没有引号,这不会产生任何有用的信息。我还查看了MSDN for the XmlNodeType,并没有说明它不受支持。
我在这里缺少什么? 如何从 XML 声明片段中获取 XmlTextReader
实例?
注意,我的目标只是确定部分构建的 XML 文档的编码,我假设它至少包含一个声明节点;因此,我正在尝试获取reader.Encoding
。如果有其他方法可以做到这一点,我愿意接受。
目前,我正在使用正则表达式手动解析声明,这不是最好的方法。
【问题讨论】:
【参考方案1】:更新:从 XML 文档或 XML 片段中获取编码:
这是一种无需使用假根即可获得编码的方法,使用XmlReader.Create。
private static string GetXmlEncoding(string xmlString)
if (string.IsNullOrWhiteSpace(xmlString)) throw new ArgumentException("The provided string value is null or empty.");
using (var stringReader = new StringReader(xmlString))
var settings = new XmlReaderSettings ConformanceLevel = ConformanceLevel.Fragment ;
using (var xmlReader = XmlReader.Create(stringReader, settings))
if (!xmlReader.Read()) throw new ArgumentException(
"The provided XML string does not contain enough data to be valid XML (see https://msdn.microsoft.com/en-us/library/system.xml.xmlreader.read)");
var result = xmlReader.GetAttribute("encoding");
return result;
这是输出,带有完整和片段的 XML:
如果你想要System.Text.Encoding,你可以修改代码如下:
private static Encoding GetXmlEncoding(string xmlString)
using (StringReader stringReader = new StringReader(xmlString))
var settings = new XmlReaderSettings ConformanceLevel = ConformanceLevel.Fragment ;
var reader = XmlReader.Create(stringReader, settings);
reader.Read();
var encoding = reader.GetAttribute("encoding");
var result = Encoding.GetEncoding(encoding);
return result;
旧答案:
正如您提到的,XmlTextReader's Encoding-property 包含编码。
这是一个完整的控制台应用程序源代码,希望对您有用:
class Program
static void Main(string[] args)
var asciiXML = @"<?xml version=""1.0"" encoding=""ASCII""?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>";
var utf8XML = @"<?xml version=""1.0"" encoding=""UTF-8""?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>";
var asciiResult = GetXmlEncoding(asciiXML);
var utfResult = GetXmlEncoding(utf8XML);
Console.WriteLine(asciiResult);
Console.WriteLine(utfResult);
Console.ReadLine();
private static Encoding GetXmlEncoding(string s)
var stream = new MemoryStream(Encoding.UTF8.GetBytes(s));
using (var xmlreader = new XmlTextReader(stream))
xmlreader.MoveToContent();
var encoding = xmlreader.Encoding;
return encoding;
这是程序的输出:
如果您知道 XML 只包含声明,也许您可以添加一个空根?比如:
var fragmentResult = GetXmlEncoding(xmlFragment + "<root/>");
【讨论】:
但是如果我只有一个声明片段,即没有其他 XML 正文,这会起作用吗?例如,我只有<?xml version=""1.0"" encoding=""ASCII""?>
。根据我的问题:“我正在编写一些代码来读取包含 XML 声明的 XML 片段,例如 "
是的,看,我试过了,我得到“root element is missing”
是的,没错。不是一个理想的解决方案,但是添加“假”根怎么样?例如: var xmlForEncodingParsing = xmlFragment + "晚上好,这是使用 System.Text.Encoding 作为输出的解决方案。 我说的很清楚,一步一步来。
class Program
static void Main(string[] args)
var line = File.ReadLines(YourFileName).First();
var correctXml = line + "<Root></Root>";
var xml = XDocument.Parse(correctXml);
var stringEncoding = xml.Declaration.Encoding;
var encoding = System.Text.Encoding.GetEncoding(stringEncoding);
【讨论】:
实际上,xml.Declaration.Encoding
是 string
而不是 System.Text.Encoding
。你能添加一些代码来实现吗?
你好 roryap !我更新了解决方案以满足您的要求。【参考方案3】:
也许晚了,但您可以在将以下代码加载到 XmlDocument 后使用它
static string getEncoding(XmlDocument xml)
if (xml.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
return (xml.FirstChild as XmlDeclaration).Encoding;
return "utf-8";
【讨论】:
【参考方案4】:如果您有一个字节数组作为输入,请尝试以下操作:
private Encoding getEncoding(byte[] data)
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream(data);
XmlReader reader = XmlReader.Create(ms, settings);
doc.Load(reader);
XmlDeclaration declaration = doc.ChildNodes.OfType<XmlDeclaration>().FirstOrDefault();
return Encoding.GetEncoding(declaration.Encoding);
【讨论】:
以上是关于从 XML 声明片段获取 XML 编码:部分内容解析不支持 XmlDeclaration的主要内容,如果未能解决你的问题,请参考以下文章