草庐IT

c# - XmlReader 不考虑文档类型符号

coder 2024-07-01 原文

第一次在这些论坛上写文章。虽然已经阅读了很长时间。

我在尝试使用 .Net 中的 XmlReader 验证 Xml 文件时遇到问题。

XML文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
  <!NOTATION png PUBLIC "-//W3C//NOTATION Portable Network Graphics//EN">
  <!ENTITY mypic SYSTEM "mypic.png" NDATA png>
]>
<root>
  <img ref="mypic" />
</root>

Xsd文件:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="myschema"
    elementFormDefault="qualified"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="img">
    <xs:complexType>
      <xs:attribute name="ref" type="xs:ENTITY" />
    </xs:complexType>
  </xs:element>

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="img" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

C# 片段:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationEventHandler += settings_ValidationEventHandler;
settings.ValidationType = ValidationType.Schema;
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessIdentityConstraints
            | XmlSchemaValidationFlags.ProcessInlineSchema
            | XmlSchemaValidationFlags.ProcessSchemaLocation
            | XmlSchemaValidationFlags.ReportValidationWarnings;

using (XmlReader reader = XmlReader.Create("myschema.xsd")) 
{
    settings.Schemas.Add(XmlSchema.Read(reader, new ValidationEventHandler(settings_ValidationEventHandler)));
}

using (XmlReader reader = XmlReader.Create("mydata.xml", settings))
{
    while (reader.Read()) ;
}

我收到一条验证错误:

Reference to an unparsed entity, 'mypic'.

根据其他验证器,它会验证,但不会根据 XmlReader。

我已经尝试了所有我能想到的方法,所以现在我求助于你们。 非常感谢任何帮助。

最佳答案

通过使用 Reflector,我发现 NOTATION 和 ENTITY 声明确实得到了应有的解析。

验证器将找到您的 mypic 实体引用并将其视为外部且未解析,因为它具有非空的 NDATA 声明。

但是,我还发现每当遇到未解析的实体引用时,验证器总是会发送一个Reference to unparsed entity验证错误。

我不明白为什么 Microsoft 将此报告为错误。在我看来,验证器应该忽略未解析的实体引用或将它们报告为警告,而不是错误。

忽略来自验证器的这些错误并仍然认为 XML 有效应该是安全的,当然,除非报告任何其他错误。

那么,如何确定报告的错误是否是可忽略的Reference to an unparsed entity-error?

我看到三个选项:

  1. 检查错误消息是否以字符串 Reference to an unparsed entity 开头。如果您的代码在非英语平台上运行,这将中断。

  2. 使用反射获取内部GetRes 属性的值,看它是否等于Sch_UnparsedEntityRef。如果 Microsoft 决定更改内部 API,这将中断。

  3. 序列化异常,判断序列化后的res成员是否等于Sch_UnparsedEntityRef。如果 Microsoft 决定更改序列化格式,这将中断。

所有这些选项都是“黑客”。第一个最有可能坏掉。然而,第三个应该是安全的。 Microsoft 不太可能更改序列化格式,因为这可能会破坏与其他代码的兼容性。

以下是如何确定是否忽略在 settings_ValidationEventHandler 方法中收到的验证异常的示例。

基于错误信息(不安全):

    static bool IsUnparsedEntityReferenceError_BasedOnMessage(
        XmlSchemaException error)
    {
        return error != null && error.Message.StartsWith(
            "Reference to an unparsed entity", StringComparison.Ordinal);
    }

基于反射(相当安全):

    static readonly PropertyInfo GetResProp = typeof(XmlSchemaException)
        .GetProperty("GetRes", BindingFlags.NonPublic | BindingFlags.Instance);

    static bool IsUnparsedEntityReferenceError_BasedOnReflection(
        XmlSchemaException error)
    {
        return error != null && GetResProp != null && 
            "Sch_UnparsedEntityRef".Equals(GetResProp.GetValue(error, null));
    }

基于序列化格式(最安全):

    static bool IsUnparsedEntityReferenceError_BasedOnSerializer(
        XmlSchemaException error)
    {
        if (error == null)
        {
            return false;
        }
        else
        {
            SerializationInfo info = new SerializationInfo(
                typeof(XmlSchemaException), new FormatterConverter());

            error.GetObjectData(info, default(StreamingContext));
            return "Sch_UnparsedEntityRef" == info.GetString("res");
        }
    }

关于c# - XmlReader 不考虑文档类型符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13366440/

有关c# - XmlReader 不考虑文档类型符号的更多相关文章

  1. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  2. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  5. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  6. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  7. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  8. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

  9. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  10. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

随机推荐