没有Unicode字节顺序标记。无法切换到Unicode。

55

我正在使用XSD编写XML验证器。

以下是我的代码,但当验证器到达while (list.Read())这一行时,会给我报错:

没有Unicode字节顺序标记。无法切换到Unicode。

有人能帮我解决吗?

public class Validator
    {
        public void Validate(string xmlString)
        {
            Boolean bRet = true;
            string xmlPath = @"C:\x.xml";
            string xsdPath = @"C:\general.xsd";

            XmlReaderSettings Settings = new XmlReaderSettings();
            Settings.Schemas.Add("", xsdPath);
            Settings.ValidationType = ValidationType.Schema;
            Settings.ValidationEventHandler += 
               new ValidationEventHandler(SettingsValidationEventHandler);

            XmlReader list = XmlReader.Create(xmlPath, Settings);
            //StringBuilder output = new StringBuilder();
            while (list.Read()) 
            {
            }
            //File.WriteAllText(@"D:\Output.xml", output.ToString());
        }
        static void SettingsValidationEventHandler(object sender,
                                                   ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Warning)
            {
                MessageBox.Show( "WARNING: ");
                MessageBox.Show(e.Message);
            }
            else if (e.Severity == XmlSeverityType.Error)
            {
                MessageBox.Show("ERROR: ");
                MessageBox.Show(e.Message);
            }
        }
    }

XML

<?xml version="1.0" encoding="utf-16"?>
<FlashList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:xsd="http://www.w3.org/2001/XMLSchema" vin="xxxxxxxxxxxxx">
  <flash ECUtype="xxx" />
</FlashList>

XSD

<?xml version="1.0" encoding="utf-16"?>
<xs:schema attributeFormDefault="unqualified" 
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="FlashList">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="flash" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute type="xs:string" name="ECUtype" use="optional"/>
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
        <xs:element name="Error" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute type="xs:byte" name="code" use="optional" />
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute type="xs:string" name="vin"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

3
你确定 "physical" 文件 x.xml 的编码正确吗?请使用文本编辑器如Sublime或jEdit打开它以检查实际编码。 - potame
是的,我已经在服务器端使用从相同xsd文件生成的c#类制作了这个XML文件,并且它是格式良好的。 这段代码在客户端上,我只想使用客户端上相同的xsd验证接收到的xml文件。 - user3122648
4个回答

98

您的文件编码实际情况与XML声明中指定的编码存在冲突。例如,如果您的文件实际上使用单字节字符,则声明encoding="utf-16"并不能将其更改为使用双字节字符。

尝试从XML声明中删除冲突的编码。 将其替换为

<?xml version="1.0" encoding="utf-16"?>

和,随着

<?xml version="1.0"?>

您还可以使用LoadXML()方法将文件加载为字符串来解决问题。


4
FWIW: <?xml version="1.0" encoding="utf-8"?> 也许也能解决问题。 - LosManos
1
是的,因为 utf-8 是默认编码。 - kjhughes
12
在遇到类似错误后,这个答案帮助我解决了自己的问题。在我的情况下,我首先通过编程方式创建了xml文件,然后在稍后的时间读取和写入它。如果你想使用xmlwriter删除/更改处理指令中的编码版本,请使用writer.WriteProcessingInstruction("xml", "version='1.0'");(其中writerXmlWriter的实例)。请参见msdn文档 - Alexis Le Compte
1
解决方法“你也可以使用LoadXML()将文件加载到字符串中作为解决方法。”对我有用。 - David Smith
但问题是这个解决方法是否安全可行? - Jakub G

3
当您在XML头中声明UTF-16编码,但实际上没有以该编码保存文件时,会抛出此错误。
您可以使用简单的Windows记事本进行检查,点击“另存为”,然后在底部检查xml文件的编码(可能仍然是UTF-8,而不是UTF-16)。 记事本编码设置截图

3

如果你无法更改 XML 文件的编码格式

<?xml version="1.0"?>

另外,您还可以直接以原始xml格式阅读xml内容,而不是使用xml path加载。

XmlReader.Create(new StringReader(File.ReadAllText(fileName)));

如果你使用 XmlDocument

var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(File.ReadAllText(filePath));

2
不要使用File.ReadAllText。始终创建一个StreamReaderFileStream。不要在内存中分配文件大小的块。 - Mr. TA
2
@Mr.TA 如果是已知的小文件,比如设置或其他文件,使用File.ReadAllText完全没问题。 - A.R.

0

您可以使用StreamReader来设置编码:

  return (TReport)xmlSerializer.Deserialize(
      new StreamReader(
          new FileStream(filename, FileMode.Open, FileAccess.Read), Encoding.UTF8));

根据您的应用程序,使用字符串传递xml可能不是最佳选择,考虑使用流。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接