从XML声明片段获取XML编码:部分内容解析不支持XmlDeclaration

时间:2015-12-15 15:33:41

标签: c# .net xml parsing encoding

我正在研究一些代码来读取包含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.XmlException构造函数时收到System.Xml.XmlTextReader,并显示错误消息:

  

部分内容不支持XmlNodeType XmlDeclaration   解析。

我用引号搜索了这个错误 - 找到的结果完全为零(编辑:现在有一个结果:这篇文章) - 并且没有引号,这没有任何用处。我也看了MSDN for the XmlNodeType,并没有说它没有被支持。

我在这里缺少什么? 如何从XML声明片段中获取XmlTextReader实例

注意,我的目标只是确定部分构建的XML文档的编码,其中我假设它至少包含一个声明节点;因此,我试图获得reader.Encoding。如果有另一种方法可以做到这一点,我对此持开放态度。

目前,我正在使用正则表达式手动解析声明,这不是最好的方法。

4 个答案:

答案 0 :(得分:4)

更新:从XML文档或XML片段获取编码:

这是一种使用XmlReader.Create获取编码而无需诉诸伪root的方法。

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:

XML encoding ith XmlReader.Create

如果您想拥有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 - 属性包含编码。

这是一个完整的控制台应用的源代码,希望它很有用:

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 Encoding output

如果你知道XML只包含声明,也许你可以添加一个空根?例如:

        var fragmentResult = GetXmlEncoding(xmlFragment + "<root/>");

XML Fragment

答案 1 :(得分:3)

晚上好,这是使用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);
    }
}

答案 2 :(得分:0)

可能会迟到,但在XmlDocument中加载后可以使用下面的代码

    static string getEncoding(XmlDocument xml)
    {
        if (xml.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
        {
            return (xml.FirstChild as XmlDeclaration).Encoding;
        }
        return "utf-8";
    }

答案 3 :(得分:0)

如果你有一个字节数组作为输入,尝试这样的事情:

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);
        }